/*!
 * Bible Library 1.6
 * Copyright(c) 2011 Bible, 
 * http://www.nicolaematei.wordpress.com
 */
var i18n = {
    add: 'Adaugă',
    langCode: 'ro',
    bible: 'Biblia',
    backgroundColor: 'Culoare de fundal',
    general: 'General',
    login: 'Login',
    logout: 'Ieşire',
    cancel: 'Anulare',
    close: 'Închide',
    copyText: 'Copiază',
    connecting: 'Conectare...',
    email: 'E-Mail',
    error: 'Eroare',
    failed: 'Eşuat',
    info: 'Informaţii',
    warning: 'Avertizare',
    normalLogin: 'Logare normală',
    zoomIn: 'Măreşte textul',
    zoomOut: 'Micşorează textul',
    search: 'Căutare',
    advancedSearch: 'Căutare avansată',
    searchType: 'Tip de Căutare',
    searchIn: 'Căutare în',
	comments: 'Comentarii',
	titles: 'Titluri',
    theme: 'Tema',
    chapterTheme: 'Tema Capitolului',
    bookOverview: 'Privire de ansamblu asupra cărţilor',
	showHideComments: 'Comentarii',
    references: 'Trimiteri',
	register: 'Înregistrare',
    resetPassword: 'Resetare parolă',
    remove: 'Şterge',
    verse: 'Verset',
    entireBible: 'Toată Biblia',
    filter: 'Filtrează',
    password: 'Parolă',
    changePassword: 'Schimbă parola',
    confirmPassword : 'Confirmare parolă',
    forgotPassword : 'Ţi-ai uitat parola?',
    oldPassword: 'Parola veche',
	passNotMatch: 'Parola nu coincide',
    passNotValid: 'Parola nu este validă',
    passWrong: 'Parolă greşită',
    preferences: 'Preferinţe',
    save: 'Salvează',
    saveAndClose: 'Salvează şi Închide',
    saving: 'Salvează',
    keywords: 'Cuvinte cheie',
    clickToEdit: 'Click pentru editare',
    saveNotLoggedMsg: 'Trebuie să fiţi logat pentru a putea salva preferinţele!',
    requestTimeout: 'Serverul nu răspunde în timp util.',
    unknownError: 'Comunicarea cu serverul a esuat!',
    authenticationRequired: 'Acţiunea nu poate fi efectuată pentru că nu sunteţi autorizat! Posibil sesiunea dvs. a expirat, vă rugăm să vă relogaţi.'
};


if(Ext.ux.TabCloseMenu){
    Ext.apply(Ext.ux.TabCloseMenu.prototype, {
        closeTabText        : "Închide Tab-ul",
        closeOtherTabsText  : "Închide celelalte Tab-uri",
        closeAllTabsText    : "Închide toate Tab-urile"
    });
}/**
 * @class Bible
 * Bible core utilities and functions.
 * @singleton
 */
var Bible = {
    /**
     * The version of the framework
     * @type String
     */
    version : '1.6',

    /**
     * logging This property controls all js logging into firebug. SET IT TO FALSE for production deployment. <br />
     * @type Boolean
     */
    logging: true,

    /**
     * @type Object
     */
    loggedUser: BibleLoggedUser,

    stateId: 'Bible',

    // global packages
    common: {},
    data: {},
    form: {},
    grid: {},
    util: {},
    plugins: {},

    // project packages
    records: {
        keywords: BibleRecordsKeywords
    },

    searchPageSize: 10,

    // default values
    defaults: {
        layout: 'box',
        references: false,
        titles: true,
        fontSize: 14
    }
};

delete BibleLoggedUser;
delete BibleRecordsKeywords;

Bible.records.books = [
    [1,  "Genesa", 50],
    [2,  "Exodul", 40],
    [3,  "Leviticul", 27],
    [4,  "Numeri", 36],
    [5,  "Deuteronomul", 34],
    [6,  "Iosua", 24],
    [7,  "Judec\u0103tori", 21],
    [8,  "Rut", 4],
    [9,  "1 Samuel", 31],
    [10, "2 Samuel", 24],
    [11, "1 \u00cemp\u0103ra\u0163i", 22],
    [12, "2 \u00cemp\u0103ra\u0163i", 25],
    [13, "1 Cronici", 29],
    [14, "2 Cronici", 36],
    [15, "Ezra", 10],
    [16, "Neemia", 13],
    [17, "Estera", 10],
    [18, "Iov", 42],
    [19, "Psalmi", 150],
    [20, "Proverbe", 31],
    [21, "Eclesiastul", 12],
    [22, "C\u00e2ntarea c\u00e2nt\u0103rilor", 8],
    [23, "Isaia", 66],
    [24, "Ieremia", 52],
    [25, "Pl\u00e2ngerile lui Ieremia", 5],
    [26, "Ezechiel", 48],
    [27, "Daniel", 12],
    [28, "Osea", 14],
    [29, "Ioel", 3],
    [30, "Amos", 9],
    [31, "Obadia", 1],
    [32, "Iona", 4],
    [33, "Mica", 7],
    [34, "Naum", 3],
    [35, "Habacuc", 3],
    [36, "\u0162efania", 3],
    [37, "Hagai", 2],
    [38, "Zaharia", 14],
    [39, "Maleahi", 4],
    [40, "Matei", 28],
    [41, "Marcu", 16],
    [42, "Luca", 24],
    [43, "Ioan", 21],
    [44, "Faptele Apostolilor", 28],
    [45, "Romani", 16],
    [46, "1 Corinteni", 16],
    [47, "2 Corinteni", 13],
    [48, "Galateni", 6],
    [49, "Efeseni", 6],
    [50, "Filipeni", 4],
    [51, "Coloseni", 4],
    [52, "1 Tesaloniceni", 5],
    [53, "2 Tesaloniceni", 3],
    [54, "1 Timotei", 6],
    [55, "2 Timotei", 4],
    [56, "Tit", 3],
    [57, "Filimon", 1],
    [58, "Evrei", 13],
    [59, "Iacov", 5],
    [60, "1 Petru", 5],
    [61, "2 Petru", 3],
    [62, "1 Ioan", 5],
    [63, "2 Ioan", 1],
    [64, "3 Ioan", 1],
    [65, "Iuda", 1],
    [66, "Apocalipsa", 22]
];


/**
 * deepCloneObject
 * Function that deep-clones a javascript object.
 *
 * @param {Object} obj javascript-object
 * @return {Object} c cloned javascript-object
 */
Bible.deepCloneObject = function(obj) {
    if (typeof obj !== 'object' || obj == null) {
        return obj;
    }

    var c = obj instanceof Array ? [] : {};

    for (var i in obj) {
        var prop = obj[i];
        if (typeof prop == 'object') {
            if (prop instanceof Array) {
                c[i] = [];
                for (var j = 0; j < prop.length; j++) {
                    if (typeof prop[j] != 'object') {
                        c[i].push(prop[j]);
                    } else {
                        c[i].push(Bible.deepCloneObject(prop[j]));
                    }
                }
            } else {
                c[i] = Bible.deepCloneObject(prop);
            }
        } else {
            c[i] = prop;
        }
    }

    return c;
};

/**
 * Method used to compare 2 objects.
 *
 * @param {Object} one the first object
 * @param {Object} two the second object
 * @param {Array} skippedProperties - optional array of properties to be skipped by this comparison
 * @return {Boolean}
 */
Bible.deepEquals = function(one, two, skippedProperties) {

    /**
     * Returns true if object one equals object two
     * @private
     * @param one
     * @param two
     */
    function objectEquals(one, two, skippedProperties) {
        var equals = true;
        if (!one || !two){
            return false;
        }

        for (var propertyName in one) {

            if (skippedProperties.indexOf(propertyName) > -1) {
                continue;
            }

            if (one[propertyName] != null && two[propertyName] == null) {
                //                //--console.log("false ",one,' or ', two, ' no prop ', propertyName);
                equals = false;
            }
            else if (one[propertyName] != null && two[propertyName] != null) {
                if (typeof one[propertyName] == 'object' &&  typeof two[propertyName] == 'object') {
                    equals = equals && Bible.deepEquals(one[propertyName], two[propertyName], skippedProperties);
                } else {
                    equals = equals && (one[propertyName]==two[propertyName]);
                }
            }
        }

        return equals;
    }

    var oneEqualsTwo = objectEquals(one, two, skippedProperties || []),
        twoEqualsOne = objectEquals(two, one, skippedProperties || []);

    return (oneEqualsTwo && twoEqualsOne);
};

(function(){
    var VERSE_URL = 'servlets/verse.php',
        SPACES_REG_EXP = /  /g,
        enterRegExp      = new RegExp(Ext.escapeRe('\n'), 'g'),

		BOOK_ID_KEYS = [
			'gen', 'ex', 'lev', 'num', 'deut', 'ios', 'jud', 'rut', '1sam', '2sam', '1imp', '2imp', '1cro', '2cro', 'ezra', 'neem', 'est', 'iov', 'ps', 'prov', 'ecl', 'cant', 'isa', 'ier', 'plan', 'ezec', 'dan', 'osea', 'ioel', 'amos', 'obad', 'iona', 'mica', 'naum', 'hab', 'tef', 'hag', 'zah', 'mal', 'mat', 'mar', 'luc', 'ioan', 'fap', 'rom', '1cor', '2cor', 'gal', 'efes', 'filip', 'col', '1tes', '2tes', '1tim', '2tim', 'tit', 'filim', 'evr', 'iac', '1pet', '2pet', '1ioan', '2ioan', '3ioan', 'iuda', 'apoc'
		],
		REF_FIND_REG_EXP = /(((Gen|Ex|Lev|Num|Deut|Ios|Jud|Rut|1\s?Sam|2\s?Sam|1\s?Împ|1\s?Imp|2\s?Împ|2\s?Imp|1\s?Cro|2\s?Cro|Ezra|Neem|Est|Iov|Ps|Prov|Ecl|Cânt|Cant|Isa|Plân|Ier|Ezec|Dan|Osea|Ioel|Amos|Obad|Iona|Mica|Naum|Hab|Ţef|Tef|Hag|Zah|Mal|Mat|Mar|Luc|Ioan|Fap|Rom|1\s?Cor|2\s?Cor|Gal|Efes|Filip|Col|1\s?Tes|2\s?Tes|1\s?Tim|2\s?Tim|Tit|Filim|Evr|Iac|1\s?Pet|2\s?Pet|1\s?Ioan|2\s?Ioan|3\s?Ioan|Iuda|Apoc)\w*\s?\w*\s?\w*)\s(\d+)\.(\d+)(-\d+)?)/gi,
		
        // diacritics RegExp
        CHAR_ESCAPE_A_REG_EXP = /([aâă])/gi,
        CHAR_ESCAPE_I_REG_EXP = /([iî])/gi,
        CHAR_ESCAPE_S_REG_EXP = /([sş])/gi,
        CHAR_ESCAPE_T_REG_EXP = /([tţ])/gi;
		
	function removeDiacritics(text) {
		return text.replace(CHAR_ESCAPE_A_REG_EXP, "a").
					replace(CHAR_ESCAPE_I_REG_EXP, "i").
					replace(CHAR_ESCAPE_S_REG_EXP, "s").
					replace(CHAR_ESCAPE_T_REG_EXP, "t");
	}
			
	function findRefInsideText(fullMatch, total, bookLong, book, chapter, verse) {
		book = removeDiacritics(book.replace(' ', '').toLowerCase());
		
		var idx = BOOK_ID_KEYS.indexOf(book);
		if(idx > -1){
			var r = removeDiacritics(Bible.records.books[idx][1].replace(' ', '').toLowerCase());
			bookLong = removeDiacritics(bookLong.replace(' ', '').toLowerCase());
			////--console.debug(r, bookLong);
			// if record text did not match
			if(r.indexOf(bookLong) != 0){
				idx = -1;
			}
		}
		book = idx + 1;
		if(book > 0){
			return ['<span class="ref" ext:qwidth="200" ext:qtip=" " ext:qurl="',
				VERSE_URL,
				'?b=', book,
				'&c=', chapter,
				'&v=', verse,
				'">', fullMatch, '</span>'
			].join('');
		} else {
			return fullMatch;
		}
	}

    Ext.apply(Bible, {
        /**
         * renderer Terms Highlight
         * @param {Object} val
         * @param {Object} metaData
         * @param {Ext.data.Record} record
         * @param {Number} rowIndex
         * @param {Number} colIndex
         * @param {Ext.data.Store} store
         */
        rendererHighlight : function(val, metaData, record, rowIndex, colIndex, store) {
            var searchField = store.searchField,
                showKeywords = store.showKeywords;
            ////--console.debug('rendererHighlight showKeywords', showKeywords);
            if((!searchField || !searchField.hasSearch) && !showKeywords){
                return val;
            }
            val = Bible.highlightTerms(val, store).text;
            return val;
        },

        /**
         * @param {String} v
         * @return {String} v
         */
        rendererComments : function(v){
            v = Ext.util.Format.htmlEncode(v);
			v = v.replace(REF_FIND_REG_EXP, findRefInsideText);
            v = v.replace(enterRegExp, '<br/>');
            v = v.replace(SPACES_REG_EXP, ' &nbsp;');
            return v;
        },

        /**
         * Escapes diacritics in the passed string for use in a regular expression
         * @param {String} s
         * @return {String}
         */
        escapeDiacriticsRe : function(s){
            return s.replace(CHAR_ESCAPE_A_REG_EXP, "[aâă]").
                replace(CHAR_ESCAPE_I_REG_EXP, "[iî]").
                replace(CHAR_ESCAPE_S_REG_EXP, "[sş]").
                replace(CHAR_ESCAPE_T_REG_EXP, "[tţ]");
        },

		highlightTerms : function(val, store) {
            var searchField = store.searchField,
                showKeywords = true,
                //showKeywords = store.showKeywords,
                highlightsTerms = searchField ? searchField.highlightsTerms : [];
            return Bible.highlightText(val, highlightsTerms, showKeywords);
        },
		
        /**
         * @param {String} val
         * @param {String/Array} defaultTerms a Term or Array of Terms
         * @return {String} val highlighted value
         */
        highlightText : function(val, defaultTerms, showKeywords) {
            var KeywordsStore = Bible.data.KeywordsStore,
                terms = [];
            if(showKeywords){
                terms = [].concat(KeywordsStore.keywordsReplace);
            }
			if(defaultTerms){
				////--console.debug('defaultTerms', defaultTerms);
				terms = terms.concat(defaultTerms);
			}
            return Ext.util.Terminology.highlight(val, terms);
        },

        /**
         * @return {Object/JSON}
         */
        getActions : function(){
            var actions = window.location.hash.split('#')[1],
                stateProvider = Ext.state.Manager.getProvider();
            return Ext.urlDecode(actions ? actions : stateProvider.get(this.stateId));
        },

        /**
         *
         * @param {String} properties
         */
        getAction : function(properties){
          var ps = Bible.getActions();
          return ps[properties];
        },

        /**
         *
         * @param {String} properties
         * @param {Object} value
         */
        setActions : function(properties, value){
            var ps = Bible.getActions(),
                stateProvider = Ext.state.Manager.getProvider(),
                encoded;
            ps[properties] = value;
            encoded = Ext.urlEncode(ps);
            stateProvider.set(this.stateId, encoded);
            window.location.hash = encoded;
        },

        /**
         *
         * @param {String} properties
         */
        removeAction : function(properties){
            var ps = Bible.getActions(),
                stateProvider = Ext.state.Manager.getProvider(),
                encoded;
            delete ps[properties];
            encoded = Ext.urlEncode(ps);
            stateProvider.set(this.stateId, encoded);
            window.location.hash = encoded;
        },

        /**
         *
         */
        isLogged : function(){
            return !!Bible.loggedUser;
        },

        /**
         *
         * @param {String} message
         * @param {String} title (optional)
         * @param {Function} fn (optional) messageBox callback
         */
        info: function(message, title, fn){
            this.showMsg('INFO', message, title, fn);
        },

        /**
         *
         * @param {String} message
         * @param {String} title (optional)
         * @param {Function} fn (optional) messageBox callback
         */
        error: function(message, title, fn){
            this.showMsg('ERROR', message, title, fn);
        },

        /**
         *
         * @param {String} message
         * @param {String} title (optional)
         * @param {Function} fn (optional) messageBox callback
         */
        warning: function(message, title, fn){
            this.showMsg('WARNING', message, title, fn);
        },

        /**
         *
         * @param {String} level
         * @param {String} message
         * @param {String} title (optional)
         * @param {Function} fn (optional) messageBox callback
         */
        showMsg: function(level, message, title, fn){
            //--console.info('showMsg: ', level, message, title);
            var d = Ext.Msg.getDialog("&#160;");
            if(d && d.proxy){
                delete d.animateTarget;
                d.proxy.stopFx();
            }
            Ext.Msg.show({
                title: title || i18n[level.toLowerCase()],
                msg: message,
                buttons: Ext.Msg.OK,
                minWidth: 300,
                animEl: 'app-name-version',
                icon: Ext.MessageBox[level],
                fn: fn || function(){}
            });
        },

        notifyNotLogged: function(){
            Bible.Notification.msg(i18n.login, i18n.saveNotLoggedMsg);
        },

        /**
         *
         */
        doLogout : function() {
            Ext.Ajax.request({
                url: 'auth.php?action=logout',
                success: function(){
                    //--console.debug('doLogout success');
                    Bible.EventManager.fireEvent('logout');
                    // TODO fix IE Bug that is not showing the last action
//                    window.location = '/'+window.location.hash;
                    window.location = '/';
                }
            });
            //TODO local hide buttons
            //window.location.reload();
//            window.location.href = 'auth.php?action=logout#' + window.location.hash;
        }
    });


    /**
     * @private
     * @param {JSON} response
     */
    function showMessage(response){
        // TODO remove all : TODO automaticaly message
        var message = response.message;
        if(message){
            Bible.showMsg(response.level, message, response.title);
        }
        // Bible.Notification.msg();
    }

    function getJsonResponse(response, options){
        // TODO try to not decode ajax request if ajax request does not need to have json response
        var jsonResponse;
        try {
            jsonResponse = Ext.decode(response.responseText, /* safe */ true);
            response.responseJson = jsonResponse;
            response.responseSuccess = jsonResponse.success;
            return jsonResponse;
        } catch (err){
//            //--console.warn('requestexception can not decode', response);
        }
        return false;
    }

    function onRequestComplete(connection, response, options) {
        var jsonResponse = getJsonResponse(response, options);
        if (jsonResponse) {
            showMessage(jsonResponse);
        }
    }

    function onRequestException(connection, response, options, e) {
        //--console.warn('requestexception', response, connection);
        if (response.isTimeout){
            //--console.warn("Timeout: ", options);
            Bible.Notification.msg(i18n.error, i18n.requestTimeout);
        } else {
            var jsonResponse = getJsonResponse(response, options);
            if (jsonResponse) {
                if (jsonResponse.unauthorized === true) {
                    Bible.warning(i18n.authenticationRequired, i18n.warning, function(){
                        window.location = '/';
                    });
                } else {
                    showMessage(jsonResponse);
                }
            } else {
                Bible.Notification.msg(i18n.error, i18n.unknownError);
            }
        }
    }

    /**
     * @override Ext.data.Connection
     * to handle all connection exceptions and messages that server returned.
     */
    Ext.override(Ext.data.Connection, {
        handleResponse: Ext.data.Connection.prototype.handleResponse.createInterceptor(function(response) {
            var options = response.argument.options;
            onRequestComplete(this, response, options);
        }),
        handleFailure: Ext.data.Connection.prototype.handleFailure.createInterceptor(function(response, e) {
            var options = response.argument.options;
            onRequestException(this, response, options, e);
        })
    });

})();

/**
 * @param {String} action
 * @param {Object} e
 * @param {String} servletUrl
 */
Bible.updateDBObj = function(action, e, servletUrl, success, scope) {
    var record = e.record;
    if(Bible.isLogged()){
        Ext.Ajax.request({
            url: servletUrl,
            success:function(response) {
                if(response.responseSuccess) {
                    record.commit();
                    if(success){
                        success.call(scope || window);
                    }
                } else {
                    record.reject();
                }
            },
            params: {
                action: action,
                field: e.field,
                value: e.value,
                id: record.id
            }
        });
    } else {
        //TODO save in cache
        //--console.warn('TODO save in cache');
//        record.commit();
        if(success){
            success.call(scope || window);
        }
        Bible.notifyNotLogged();
    }
};

Bible.copyToClipboard = function (s) {
    // ie
    if (window.clipboardData && clipboardData.setData) {
        clipboardData.setData('text', s);
    } else { // others
        // TODO
//        var flashCopier = 'flashcopier';
//        if(!document.getElementById(flashcopier)) {
//            var divHolder = document.createElement('div');
//            divHolder.id = flashCopier;
//            document.body.appendChild(divHolder);
//        }
//        document.getElementById(flashCopier).innerHTML = '';
//        var divInfo = '<embed src="_clipboard.swf" FlashVars="clipboard='+encodeURIComponent(s)+'" width="0" height="0" type="application/x-shockwave-flash"></embed>';
//        document.getElementById(flashCopier).innerHTML = divInfo;
    }
};

/**
 *
 */
Bible.doLogin = function() {
    var username = 'email',
        password = 'password',
        waitMsg = i18n.connecting;
    if(!this.loginWin){
        function showNormalLogin(show){
            //--console.debug('showNormalLogin', show);
            waitMsg = show ? i18n.connecting : i18n.resetPassword;
            var form = formPanel.getForm();
            form.findField('action').setValue(show ? 'login' : 'resetpasswd');
            form.findField(password).setDisabled(!show);
            if(!show){
                form.findField(password).reset();
            }

            formPanel.resetPassword.setVisible(!show);
            formPanel.login.setVisible(show);

            form.findField('forgotPassword').setVisible(show);
            form.findField('normalLogin').setVisible(!show);
        }
        function doLoginHandler(){
            if(formPanel.getForm().isValid()){
                formPanel.getForm().submit({
                    method:'POST',
                    waitTitle: i18n.login,
                    waitMsg: waitMsg,
                    scope: this,
                    success: function(form, action) {
                        //--console.debug('success', form, action);
                        if(form.findField('action').getValue() == 'login'){
                            // simulate refresh
                            formPanel.remove(form.findField('action'));
                            form.url = window.location.href;
                            form.standardSubmit = true;
                            form.submit();
                        }
                    }
                });
            } else {
                //--console.warn('form is not valid');
            }
        }

        var formPanel = new Ext.form.FormPanel({
            labelWidth: 100,
            labelAlign: 'right',
            url:'auth.php',
            cls: 'x-panel-mc', // for background color (like frame)
            defaultType: 'textfield',
            monitorValid:true,
            bodyStyle: 'padding-top: 8px',
            defaults: {
                anchor: '-8'
            },
            keys: [
                {
                    key: Ext.EventObject.ENTER,
                    scope: this,
                    fn: doLoginHandler
                }
            ],
            items:[
                {
                    xtype: 'hidden',
                    name: 'action',
                    value: 'login'
                },
                {
                    fieldLabel: i18n.email,
                    name: username,
                    el: 'input_username',
                    vtype: 'email',
                    allowBlank:false
                },
                {
                    fieldLabel: i18n.password,
                    name: password,
                    el: 'input_password',
                    inputType:'password',
                    minLength: 6,
                    allowBlank: false
                },
                {
                    xtype: 'displayfield',
                    name: 'forgotPassword',
                    value: '<a href="#" >'+i18n.forgotPassword+'</a>',
                    listeners: {
                        afterrender: function(){
                            this.el.select('a').on('click',function(){
                                showNormalLogin(false);
                            }, this);
                        }
                    }
                },
                {
                    xtype: 'displayfield',
                    name: 'normalLogin',
                    hidden: true,
                    value: '<a href="#" >'+i18n.normalLogin+'</a>',
                    listeners: {
                        afterrender: function(){
                            this.el.select('a').on('click',function(){
                                showNormalLogin(true);
                            }, this);
                        }
                    }
                }
            ],
            buttons:[
                {
                    text: i18n.login,
                    ref: '/login',
                    type: 'submit',
					iconCls: 'login-action',
                    formBind: true,
                    disabled: true,
                    scope: this,
                    handler: doLoginHandler
                },
                {
                    text: i18n.resetPassword,
                    ref: '/resetPassword',
                    formBind: true,
                    scope: this,
                    hidden: true,
                    handler: doLoginHandler
                },
                {
                    text: i18n.cancel,
                    scope: this,
                    handler: function(){
                        this.loginWin.hide();
                    }
                }
            ]
        });
        this.loginWin = new Ext.Window({
            title: i18n.login,
            closeAction: 'hide',
			iconCls: 'login',
            width: 350,
            autoHeight: true,
            modal: true,
            resizable: false,
            listeners: {
                show: function(){
                    showNormalLogin(true);
                    (function(){
                        formPanel.getForm().findField(username).focus();
                    }).defer(300);
                }
            },
            items: [formPanel]
        });
    }
    this.loginWin.show();
};

/**
 *
 */
Bible.showRegisterForm = function() {
    //var captchaURL = "include/captcha/CaptchaSecurityImages.php?width=100&height=40&characters=4&t=";
    if(!this.registerWin){
        function doRegisterHandler(){
            if(formPanel.getForm().isValid()){
                formPanel.getForm().submit({
                    method:'POST',
                    waitTitle: i18n.register,
                    waitMsg: i18n.connecting,
                    scope: this,
                    success:function(form, action) {
                        this.registerWin.hide();
                    }
                });
            } else {
                //--console.warn('form is not valid');
            }
        }

//        var boxCaptcha = new Ext.BoxComponent({
//            width: 150,
//            height: 40,
//            autoEl: {
//                tag:'img',
//                id: 'activateCodeImg',
//                title : 'Click pentru alt code',
//                src: captchaURL + new Date().getTime()
//            }
//        });
//        boxCaptcha.on('render',function (){
//            var curr = Ext.get('activateCodeImg');
//            //curr.on('click', this.onCapthaChange,this);
//        },this);

        var formPanel = new Ext.form.FormPanel({
            labelWidth: 100,
            labelAlign: 'right',
            url:'register.php',
            timeout: 90, // 1 min 30 sec
            method : 'POST',
            cls: 'x-panel-mc', // for background color (like frame)
            defaultType: 'textfield',
            monitorValid:true,
            bodyStyle: 'padding-top: 8px',
            defaults: {
                anchor: '-8'
            },
            keys: [
                {
                    key: Ext.EventObject.ENTER,
                    scope: this,
                    fn: doRegisterHandler
                }
            ],
            items:[
                {
                    fieldLabel: i18n.email,
                    name:'username',
                    vtype: 'email',
                    allowBlank:false
                },
                {
                    fieldLabel: i18n.password,
                    name:'password',
                    id: 'registerPassword',
                    inputType:'password',
                    allowBlank:false,
                    minLength: 6
                },
                {
                    fieldLabel: i18n.confirmPassword,
                    inputType:'password',
                    vtype: 'password',
                    initialPassField: 'registerPassword',
                    allowBlank:false
                }
//                {
//                    fieldLabel: 'Confirmare',
//                    xtype: 'compositefield',
//                    items: [{
//                        xtype: 'textfield',
//                        width: 60,
//                        name: 'confirm'
//                    },
//                    boxCaptcha
//                    ]
//                }
            ],
            buttons:[
                {
                    text: i18n.register,
                    iconCls: 'save',
                    formBind: true,
                    disabled: true,
                    scope: this,
                    handler: doRegisterHandler
                },
                {
                    text: i18n.cancel,
                    scope: this,
                    handler: function(){
                        this.registerWin.hide();
                    }
                }
            ]
        });
        this.registerWin = new Ext.Window({
            title: i18n.register,
            iconCls: 'user_add',
            closeAction: 'hide',
            width: 350,
            autoHeight: true,
            modal: true,
            resizable: false,
            items: [formPanel]
        });
    }
    this.registerWin.show();
};


(function(){
    // private
    function doSubmitHandler(formPanel, win, scope){
        if(formPanel.getForm().isValid()){
            formPanel.getForm().submit({
                method:'POST',
                waitTitle: i18n.changePassword,
                waitMsg: i18n.saving + '...',
                scope: scope,
                success:function() {
                    win.hide();
                }
            });
        } else {
            //--console.warn('form is not valid');
        }
    }

    /**
     *
     */
    Bible.showResetPassWin = function() {
        if(!this.resetPassWin){
            var formPanel = new Ext.form.FormPanel({
                labelWidth: 100,
                labelAlign: 'right',
                url:'auth.php',
                timeout: 90, // 1 min 30 sec
                method : 'POST',
                cls: 'x-panel-mc', // for background color (like frame)
                defaultType: 'textfield',
                monitorValid:true,
                bodyStyle: 'padding-top: 8px',
                defaults: {
                    anchor: '-8'
                },
                keys: [
                    {
                        key: Ext.EventObject.ENTER,
                        scope: this,
                        fn: function(){
                            doSubmitHandler(formPanel, this.resetPassWin, this);
                        }
                    }
                ],
                items:[
                    {
                        xtype: 'hidden',
                        name: 'action',
                        value: 'changePassword'
                    },
                    {
                        fieldLabel: i18n.password,
                        name:'password',
                        id: 'resetPassword',
                        inputType:'password',
                        allowBlank:false,
                        minLength: 6
                    },
                    {
                        fieldLabel: i18n.confirmPassword,
                        inputType:'password',
                        vtype: 'password',
                        initialPassField: 'resetPassword',
                        allowBlank:false
                    }
                ],
                buttons:[
                    {
                        text: i18n.save,
                        iconCls: 'save',
                        formBind: true,
                        disabled: true,
                        scope: this,
                        handler: function(){
                            doSubmitHandler(formPanel, this.resetPassWin, this);
                        }
                    }
                ]
            });

            /**
             * @property resetPassWin
             * @type Ext.Window
             */
            this.resetPassWin = new Ext.Window({
                title: i18n.changePassword,
                iconCls: 'key',
                closeAction: 'hide',
                width: 350,
                autoHeight: true,
                modal: true,
                closable: false,
                resizable: false,
                items: [formPanel]
            });
        }
        this.resetPassWin.show();
    };

    /**
     *
     */
    Bible.showChangePassWin = function() {
        if(!this.changePassWin){
            var formPanel = new Ext.form.FormPanel({
                labelWidth: 100,
                labelAlign: 'right',
                url:'auth.php',
                timeout: 90, // 1 min 30 sec
                method : 'POST',
                cls: 'x-panel-mc', // for background color (like frame)
                defaultType: 'textfield',
                monitorValid:true,
                bodyStyle: 'padding-top: 8px',
                defaults: {
                    anchor: '-8'
                },
                keys: [
                    {
                        key: Ext.EventObject.ENTER,
                        scope: this,
                        fn: function(){
                            doSubmitHandler(formPanel, this.changePassWin, this);
                        }
                    }
                ],
                items:[
                    {
                        xtype: 'hidden',
                        name: 'action',
                        value: 'changePassword'
                    },
                    {
                        fieldLabel: i18n.oldPassword,
                        name:'oldPassword',
                        inputType:'password',
                        allowBlank:false,
                        minLength: 6
                    },
                    {
                        fieldLabel: i18n.password,
                        name:'password',
                        id: 'changePassword',
                        inputType:'password',
                        allowBlank:false,
                        minLength: 6
                    },
                    {
                        fieldLabel: i18n.confirmPassword,
                        inputType:'password',
                        vtype: 'password',
                        initialPassField: 'changePassword',
                        allowBlank:false
                    }
                ],
                buttons:[
                    {
                        text: i18n.save,
                        iconCls: 'save',
                        formBind: true,
                        disabled: true,
                        scope: this,
                        handler: function(){
                            doSubmitHandler(formPanel, this.changePassWin, this);
                        }
                    },
                    {
                        text: i18n.cancel,
                        scope: this,
                        handler: function(){
                            this.changePassWin.hide();
                        }
                    }
                ]
            });

            /**
             * @property changePassWin
             * @type Ext.Window
             */
            this.changePassWin = new Ext.Window({
                title: i18n.changePassword,
                iconCls: 'key',
                closeAction: 'hide',
                width: 350,
                autoHeight: true,
                modal: true,
                resizable: false,
                items: [formPanel]
            });
        }
        this.changePassWin.show();
    };


    /**
     *
     */
    Bible.showPreferencesWin = function() {
        if(!this.preferencesWin){
            // TODO not done change email yet
//
//            var formPanel = new Ext.form.FormPanel({
//                title: i18n.general,
//                labelWidth: 100,
//                labelAlign: 'right',
//                url:'preferences.php', // TODO
//                timeout: 90, // 1 min 30 sec
//                method : 'POST',
//                cls: 'x-panel-mc', // for background color (like frame)
//                defaultType: 'textfield',
//                monitorValid:true,
//                bodyStyle: 'padding-top: 8px',
//                defaults: {
//                    anchor: '-8'
//                },
//                keys: [
//                    {
//                        key: Ext.EventObject.ENTER,
//                        scope: this,
//                        fn: function(){
//                            //doSubmitHandler(formPanel, this.changePassWin, this);
//                        }
//                    }
//                ],
//                items:[
//                    {
//                        fieldLabel: i18n.email,
//                        name:'username',
//                        vtype: 'email',
//                        value: (Bible.loggedUser) ? Bible.loggedUser.email : 'demo@bibliaonline.ro',
//                        //disabled: true,
//						readOnly: true,
//                        allowBlank:false
//                    }
//                ],
//                buttons:[
//                    {
//                        text: i18n.save,
//                        iconCls: 'save',
//                        disabled: true
//                    },
//                    {
//                        text: i18n.cancel,
//                        disabled: true
//                    }
//                ]
//            });


            /**
             * @property preferencesWin
             * @type Ext.Window
             */
            this.preferencesWin = new Ext.Window({
                title: i18n.preferences,
                iconCls: 'preferences',
                closeAction: 'hide',
                width: 800,
                minWidth: 700,
                height: 470,
                minHeight: 300,
                maximizable: true,
                collapsible: true,
                tbar: {
                    hidden: !Bible.loggedUser,
                    items:[
                        {
                            text: i18n.changePassword,
                            iconCls: 'key',
                            scope: this,
                            handler: function(){
                                Bible.showChangePassWin();
                            }
                        },
                        '-'
                    ]
                },
                layout: 'fit',
                items: [
                    new Ext.TabPanel({
                        activeTab: 0,
                        border: false,
                        bodyBorder: false,
                        items: [
//                            formPanel,
                            new Bible.KeywordsPanel({
								ref: '/keywordsPanel',
                                border: false,
                                title: i18n.keywords
                            })
                        ]
                    })
                ]
            });
//			this.preferencesWin.keywordsPanel.saveAndCloseButton.on({
//				scope: this.preferencesWin,
//				click: function(){
//                    (function(){
//                        this.hide(); // TODO fix: add and hit saveAndClose -> when open second time grid is disabled
//                    }).defer(1000, this);
//				}
//			});
        }
        this.preferencesWin.show();
    };
})();

/**
 *
 */
Bible.showDocs = function() {
    if(!this.docWin){
        this.docWin = new Ext.Window({
            title: i18n.info,
            autoLoad: 'docs/' + i18n.langCode + '/docs.html?' + Bible.version,
            iconCls: 'icon-docs',
            bodyStyle: 'padding: 10px',
            cls: 'docs-window',
            autoScroll: true,
            closeAction: 'hide',
            width: 750,
            height: 450,
            maximizable: true,
            buttons: [
                {
                    text: i18n.close,
                    scope: this,
                    handler: function(){
                        this.docWin.hide();
                    }
                }
            ]
        });
    }
    this.docWin.show();
};

/*_logger_block_start - don't remove this line (used in build.xml)
(function(){
    function setConsoleFunction(fn, force){
        if(!window.console || !Bible.logging) {
            window.console = {};
        }

        var copyFn = force ? Ext.apply : Ext.applyIf;
        copyFn(window.console, {
            info: fn,
            log: fn,
            dir: fn,
            warn: fn,
            debug: fn,
            time: fn,
            timeEnd: fn,
            profile: fn,
            profileEnd: fn
        });
    }

    if(Bible.logging){
//        if(Ext.isIE && window.console && window.console.log){
//            setConsoleFunction(console.log, false);
//        }
        setConsoleFunction(Ext.emptyFn, false);
    } else {
        setConsoleFunction(Ext.emptyFn, true);
    }
})();
_logger_block_end*/



/**
 * @class Bible.Notification
 * @extends Object
 * @singleton
 */
Bible.Notification = (function(){
    var msgCt,
        firstTime = true;
    function createBox(t, s){
        return [
            '<div class="msg">',
                '<h3>',
                    '<div class="x-tool x-tool-close"></div>',
                    t,
                '</h3>', s,
            '</div>'
        ].join('');
    }

    return {
        /**
         * @cfg {String} id
         */
        id: 'notification-msg-div',

        /**
         * @cfg {String/Object} containerEl
         */
        /**
         * @cfg {Number} hideInterval
         */
        hideInterval: 10,

        /**
         * @cfg {String} showAnchor
         */
        showAnchor: 't',

        /**
         * @cfg {String} hideAnchor
         */
        hideAnchor: 'r',

        init: function(config){
            Ext.apply(this, config);
        },

        /**
         *
         * @param {String} title
         * @param {String/Array} format
         * @param {String} icon TODO
         */
        msg : function(title, format, icon){
            // TODO nmatei - test in chrome (first time appears in top-middle not in top-right
            var me = this,
                containerEl = me.containerEl = me.containerEl || document.body;
            if(!msgCt){
                msgCt = Ext.DomHelper.insertFirst(containerEl, {id: me.id}, true);
            }
            msgCt.alignTo(containerEl, 't-t');
            if(firstTime){
                msgCt.alignTo(containerEl, 't-t');
                firstTime = false;
            }
//            msgCt.alignTo(me.containerEl, 'tr-tr');
            var s = String.format.apply(String, Array.prototype.slice.call(arguments, 1)),
                m = Ext.DomHelper.append(msgCt, {
                    html : createBox(title, s)
                }, true);
            //--console.info('msg: ', title, s);
            m.slideIn(me.showAnchor).pause(me.hideInterval).fadeOut({remove:true});
//            m.select('span.close').on('click', function(){
            m.select('div.x-tool-close').on('click', function(){
                m.stopFx().fadeOut({remove:true});
            });
        }
    };
})();
/**
 * @class Ext.form.ColorField
 * @extends Ext.form.TriggerField
 * Provides a very simple color form field with a ColorMenu dropdown.
 * Values are stored as a six-character hex value without the '#'.
 * I.e. 'ffffff'
 * @constructor
 * Create a new ColorField
 * <br />Example:
 * <pre><code>
var cf = new Ext.form.ColorField({
	fieldLabel: 'Color',
	hiddenName:'pref_sales',
	showHexValue:true
});
</code></pre>
 * @param {Object} config
 */
Ext.form.ColorField = function(config){
    Ext.form.ColorField.superclass.constructor.call(this, config);
	this.on('render', this.handleRender);
};

Ext.form.ColorField = Ext.extend(Ext.form.TriggerField,  {
    /**
     * @cfg {Boolean} showHexValue
     * True to display the HTML Hexidecimal Color Value in the field
     * so it is manually editable.
     */
    showHexValue : false,
	
	/**
     * @cfg {String} triggerClass
     * An additional CSS class used to style the trigger button.  The trigger will always get the
     * class 'x-form-trigger' and triggerClass will be <b>appended</b> if specified (defaults to 'x-form-color-trigger'
     * which displays a calendar icon).
     */
    triggerClass : 'x-form-color-trigger',
	
    /**
     * @cfg {String/Object} autoCreate
     * A DomHelper element spec, or true for a default element spec (defaults to
     * {tag: "input", type: "text", size: "10", autocomplete: "off"})
     */
    // private
    defaultAutoCreate : {tag: "input", type: "text", size: "10",
						 autocomplete: "off", maxlength:"6"},
	
	/**
	 * @cfg {String} lengthText
	 * A string to be displayed when the length of the input field is
	 * not 3 or 6, i.e. 'fff' or 'ffccff'.
	 */
	lengthText: "Color hex values must be either 3 or 6 characters.",
	
	//text to use if blank and allowBlank is false
	blankText: "Must have a hexidecimal value in the format ABCDEF.",
	
	/**
	 * @cfg {String} color
	 * A string hex value to be used as the default color.  Defaults
	 * to 'FFFFFF' (white).
	 */
	defaultColor: 'FFFFFF',
	
	maskRe: /[a-f0-9]/i,
	// These regexes limit input and validation to hex values
	regex: /[a-f0-9]/i,

	//private
	//curColor: 'ffffff',
	
    // private
    validateValue : function(value){
		value = value.toUpperCase();
		
		if(!this.showHexValue) {
			return true;
		}
		if(value.length<1) {
			this.el.setStyle({
				'background-color':'#' + this.defaultColor
			});
			if(!this.allowBlank) {
				this.markInvalid(String.format(this.blankText, value));
				return false
			}
			//this.clearInvalid();
			this.selColor = '';
			return true;
		}
		if(value.length!=3 && value.length!=6 ) {
			this.markInvalid(String.format(this.lengthText, value));
			return false;
		}
		this.setColor(value);
        return true;
    },

    // private
    validateBlur : function(){
        return !this.menu || !this.menu.isVisible();
    },
	
	// Manually apply the invalid line image since the background
	// was previously cleared so the color would show through.
	markInvalid : function( msg ) {
		Ext.form.ColorField.superclass.markInvalid.call(this, msg);
		this.el.setStyle({
			'background-image': 'url(../lib/resources/images/default/grid/invalid_line.gif)'
		});
	},

    /**
     * Returns the current color value of the color field
     * @return {String} value The hexidecimal color value
     */
    getValue : function(){
    	if(this.selColor != undefined){
    		this.selColor = this.selColor.toUpperCase();	
    	}
		//return (this.curValue || this.defaultValue || "FFFFFF");
		//return (this.selColor || this.defaultColor || "FFFFFF");
//		return this.selColor;
		return this.selColor; // matei add
    },

    /**
     * Sets the value of the color field.  Format as hex value 'FFFFFF'
     * without the '#'.
     * @param {String} hex The color value
     */
    setValue : function(hex){
        if(hex){
            hex = hex.toUpperCase();
            hex = hex.replace('#', ''); // matei add
        }
        Ext.form.ColorField.superclass.setValue.call(this, hex);
		this.setColor(hex);
		//this.applyEmptyText();
        //this.autoSize();
        return this;
    },
    
	/**
	 * Sets the current color and changes the background.
	 * Does *not* change the value of the field.
	 * @param {String} hex The color value.
	 */
	setColor : function(hex) {
		this.curColor = hex;
		this.selColor = hex;
		
        var textColor = this.getVisibleColor(this.hex2rgb(hex)); 
		
		this.el.setStyle( {
			'background': '#' + hex +' none',
			//'background-color': '#' + hex,
			//'background-image': 'none',
			'color': textColor
		});
		if(!this.showHexValue) {
			this.el.setStyle({
				'text-indent': '-100px'
			});
			if(Ext.isIE) {
				this.el.setStyle({
					'margin-left': '100px'
				});
			}
		}
	},
	
	handleRender: function() {
		this.setDefaultColor();
	},
	
	setDefaultColor : function() {
		this.setValue(this.defaultColor);
	},

    // private
    menuListeners : {
        select: function(m, d){
            this.setValue(d);
        },
        show : function(){ // retain focus styling
            this.onFocus();
        },
        hide : function(){
            this.focus();
            var ml = this.menuListeners;
            this.menu.un("select", ml.select,  this);
            this.menu.un("show", ml.show,  this);
            this.menu.un("hide", ml.hide,  this);
        }
    },
	
	//private
	handleSelect : function(palette, selColor) {
		this.setValue(selColor);
        this.fireEvent('select', this, palette, selColor); // Matei add
	},

    // private
    // Implements the default empty TriggerField.onTriggerClick function to display the ColorPicker
    onTriggerClick : function(){
        if(this.disabled){
            return;
        }
        if(this.menu == null){
            this.menu = new Ext.menu.ColorMenu();
			this.menu.palette.on('select', this.handleSelect, this );
        }
        this.menu.on(Ext.apply({}, this.menuListeners, {
            scope:this
        }));
        this.menu.show(this.el, "tl-bl?");
    },
    
    
    // private
    hex2dec: function(hexchar) {
        return "0123456789ABCDEF".indexOf(hexchar.toUpperCase());
    },
    // private
    hex2rgb: function(color) { 
        color = color.replace("#", "");
        return {
            R : (this.hex2dec(color.substr(0, 1)) * 16) + this.hex2dec(color.substr(1, 1)),
            G : (this.hex2dec(color.substr(2, 1)) * 16) + this.hex2dec(color.substr(3, 1)),
            B : (this.hex2dec(color.substr(4, 1)) * 16) + this.hex2dec(color.substr(5, 1))
        }
    },
    
    getVisibleColor: function(rgb){
    	return ((rgb.R * 299) + (rgb.G * 587) + (rgb.B * 114)) / 1000 - 125 < 0 ? "#FFF" : "#000";
    }
});Ext.ns('Ext.ux.state');

(function(){
	/**
     * @class UserDataStorage
	 * This DataStorage implementation will be used in the case of IE6-7,
	 * that is, in the case where window.localStorage is not detected
	 * @param {Object} provider
     * @author Radu Brehar
	 */
	var UserDataStorage = function(provider){

		this.provider = provider;

		this.prefix = this.initialPrefix = 'userdatastorage-';
		this.prefix += this.provider.userid+'_';

		var textAreaId = Ext.id();

		Ext.getBody().insertHtml('beforeEnd',
		'<form>'+
			"<textarea id='"+textAreaId+"' style=\"display:none; behavior:url('#default#userData')\"></textarea>"+
		'</form>'
		);

		var storageArea = Ext.get(textAreaId),
			storageDom = storageArea.dom;

		if (!storageDom.addBehavior){
			throw 'Cannot use UserDataStorage. Browser incompatible.'
		};

		/**
		 * I have found no way to get all attributes on the element.
		 * Because of this, at each set, we update an array of existing attributes,
		 * which is set as the value for the this.initialPrefix attribute
		 * @param {Object} name
		 * @param {Object} value
		 */
		this.set = function(name, value){
			var arr = Ext.decode(storageDom.getAttribute(this.initialPrefix)) || [],
				attributeName = this.prefix+name;

			if (arr.indexOf(attributeName) == -1){
				arr.push(attributeName);
			}
			storageDom.setAttribute(this.initialPrefix, Ext.encode(arr));
			storageDom.setAttribute(attributeName, Ext.encode(value));
			storageDom.save(this.prefix);
		};

        this.clearAll = function(){
            var arr = Ext.decode(storageDom.getAttribute(this.initialPrefix)) || [];

            for (var i=0, len = arr.length; i<len; i++){
                storageDom.removeAttribute(arr[i]);
            }

            storageDom.setAttribute(this.initialPrefix, Ext.encode([]));
        };

		this.readStorage = function(){
			storageDom.load(this.prefix);

			var attributes = Ext.decode(storageDom.getAttribute(this.initialPrefix)) || [],
				len = attributes.length,
				valueObject = {}, key;

			for (var i=0; i<len; i++){
				key = attributes[i];
				if(key && key.indexOf(this.prefix) == 0){
					////--console.log('found key: ', key);
	                valueObject[key.substr(this.prefix.length)] = Ext.decode(storageDom.getAttribute(key));
					storageDom.value = storageDom.getAttribute(key);
	            }
			}
			////--console.log(Ext.encode(valueObject));

			return valueObject;
		}

	};

	var HTML5LocalStorage = function(provider){
		this.provider = provider;

		this.prefix = 'localstorage-';
		this.prefix += this.provider.userid+'_';

		this.set = function(name, value){
			////--console.log('set ',name,' to ', value);
			window.localStorage.setItem(this.prefix+name, Ext.encode(value));
		};

		this.clear = function(name){
			window.localStorage.removeItem(this.prefix+name);
		};

        this.clearAll = function(){
            window.localStorage.clear();
        };

		this.readStorage = function(){
			var storage = localStorage,
				len = storage.length,
				key,
				valueObject = {};

			////--console.log('local storage length is ', len, ' and prefix is ', this.prefix);

			for (var i=0; i<len; i++){
				key = storage.key(i);
				if(key && key.indexOf(this.prefix) == 0){
					////--console.log('found key: ', key);
	                valueObject[key.substr(this.prefix.length)] = Ext.decode(storage.getItem(key));
	            }
			}
			////--console.log('return ', valueObject);

			return valueObject;
		};
	};

    /**
     * @class Ext.ux.state.LocalProvider
     * @extends Ext.state.Provider
     * Usage:
     *   Ext.state.Manager.setProvider(new Ext.ux.state.LocalProvider({
     *       userid: <a user id>
     *   }));
     */
	var LocalProvider = Ext.extend(Ext.state.Provider,{
		/**
		 * a user id - will be useful in situations when multiple users
		 * use the same computer&browser, so the state will not be shared by them
		 * @param {Object} config
		 */
		userid: '',

	    constructor : function(config){
	        LocalProvider.superclass.constructor.call(this);

	        Ext.apply(this, config);
			/**
			 * we actually decide what storage to use by detecting existing posibilities:
			 * localStorage or userDate(in case of ie6+7)
			 * and delegate all responsabilities to the implementation
			 */
			this.actualProvider = this.getActualProvider();
	        this.state = this.actualProvider.readStorage();
            //--console.debug('state', this.state);
	    },

		getActualProvider: function(){
			if (window.localStorage) {
				////--console.log('localStorage');
				return new HTML5LocalStorage(this);
			} else if (Ext.isIE){
				////--console.log('userdataStorage');
				return new UserDataStorage(this);
			} else {
				throw 'LocalProvider not supported'
			}
		},

	    // private
	    set : function(name, value){
	        if(typeof value == "undefined" || value === null){
	            this.clear(name);
	            return;
	        }
	        this.actualProvider.set(name, value);
	        LocalProvider.superclass.set.call(this, name, value);
	    },

	    // private
	    clear : function(name){
	        this.actualProvider.clear(name);
	        LocalProvider.superclass.clear.call(this, name);
	    },

        clearAll: function(){
            this.actualProvider.clearAll();
        },

        getKeysStartingWith: function(str){
            var state = this.actualProvider.readStorage(),
                keys = [];

            for (var i in state){
                if (i.indexOf(str) == 0){
                    keys.push(i);
                }
            }

            return keys;
        }
	});

	Ext.ux.state.LocalProvider = LocalProvider;
})();
(function(){
	var scale = 'medium';
    if(deviceType == 'mobile'){
        scale = 'large';
    }
	Ext.override(Ext.Button, {
		scale: scale
	});

    var prevOnRefresh = Ext.grid.RowSelectionModel.prototype.onRefresh;

    Ext.override(Ext.grid.RowSelectionModel,{
        // TODO (nmatei) request better solution from extjs to implement fixes
        initEvents: Ext.grid.RowSelectionModel.prototype.initEvents.createSequence(function(){
            this.on({
                beforerowselect: function(){
                    this.selectionChange = true;
                },
                rowdeselect: function(sm, index, r){
                    if (!this.selectionChange){
                        ////--console.debug('CLEAR');
                        this.fireEvent('clearselection', sm, index, r); // new event - selection lost
                        if(!sm.hasSelection()){
                            this.fireEvent('clearselections', sm, index, r); // new event - no selections
                        }
                    }
                },
                rowselect: function(){
                    delete this.selectionChange;
                    ////--console.debug('ROW SELECT');
                }
            })
        }),

        // private
        onRemove : function(v, index, r){ // TODO verify original code after upgrade extjs
            var me = this;
            if(me.selections.remove(r) !== false){
                me.fireEvent('selectionchange', me);
                me.fireEvent('clearselection', me, index, r); // new event - selection lost
                if(!me.hasSelection()){
                    me.fireEvent('clearselections', me, index, r); // new event - no selections
                }
            }
        },
        
        // private
        onRefresh : function(){
            var me = this,
                s = me.hasSelection(),
                r = me.getSelections();
            prevOnRefresh.apply(me, arguments); // call original
            if(s && !me.hasSelection()){
                //var ds = me.grid.store;
                me.fireEvent('clearselections', me, -1, r[0]); // new event
            }
        }
    });
    
    /**
     * @class Ext.form.TextField 
     */
    var originalSetValue = Ext.form.TextField.prototype.setValue,
        originalGetValue = Ext.form.TextField.prototype.getValue;

    Ext.override(Ext.form.TextField, {
//        validationDelay: 1000,

        /**
         * @cfg {String} useTrim Specify <tt>false</tt> to allow start OR end spaces and not trim original value
         * (defaults to <tt>true</tt>). <tt>Ext.util.Format.trim</tt> before get/set value.
         * The supported values are <tt>true</tt>, <tt>false</tt>.
         */
        useTrim : true,

        setValue : function(v){
            if(this.useTrim){
                v = Ext.util.Format.trim(v);
            }
            originalSetValue.call(this, v);
            return this;
        },

        getValue : function(){
            var v = originalGetValue.call(this);
            if(this.useTrim){
                v = Ext.util.Format.trim(v);
            }
            return v;
        }
    });

    /**
     * @class Ext.Component
     */
    // TODO (nmatei) hack for bug: initial disabled bug in IE
    // http://www.sencha.com/forum/showthread.php?104990-FormPanel-Panel-initial-disabled-in-hbox-mask-amp-position-bug&p=492028
    if(Ext.isIE){
        Ext.override(Ext.Component, {
            render : Ext.Component.prototype.render.createSequence(function(){
                if(this.disabled){
                    (function(){
                        // pass silent so the event doesn't fire the first time.
                        if (this.disabled){ // this.disabled could be changed in the meantime
                            this.disable(true);
                        }
                    }).defer(1, this); // like java Thread.yield :)
                }
            })
        });
    }

	Ext.override(Ext.form.ComboBox, {
		postBlur: Ext.form.ComboBox.prototype.postBlur.createSequence(function(){
			if(this.editable && this.clearFilterOnReset && this.mode == 'local'){
				//--console.debug('ComboBox.postBlur -> store.clearFilter');
				this.store.clearFilter();
			}
		})
	});


    Ext.override(Ext.ux.form.SearchField, {
        minChars: 3,
		
		keyupTaskDelay: 300,

        initEvents : Ext.ux.form.SearchField.prototype.initEvents.createSequence(function(){
            var me = this;
            if(me.onKeyup) {
                me.el.on('keyup', me.onKeyupAction, me);
            }
        }),
		
		// private
		onKeyupAction: function(){
			var me = this;
			if (!me.searchTask) {
				me.searchTask = new Ext.util.DelayedTask(me.onTrigger2Click, me);
			}
			me.searchTask.delay(me.keyupTaskDelay);
		},
		
		onTrigger1Click : function(){
			var me = this;
			if(me.hasSearch){
				me.el.dom.value = '';
				var o = {start: 0},
					store = me.store;
				store.baseParams = store.baseParams || {};
				store.baseParams[me.paramName] = '';
				store.removeAll();
				me.triggers[0].hide();
				me.hasSearch = false;
			}
		},

        onTrigger2Click : function(){
            var me = this,
                v = me.getRawValue();
			me.highlightsTerms = [];
            if(v.length < me.minChars){
                //me.onTrigger1Click();
                return;
            }
			// matei add
			var split = me.store.baseParams.type != 'text',
			    highlights = Ext.util.Terminology.createHighlightsTerms(v, me.minChars, split);
			me.highlightsTerms = highlights.terms;
			
            var o = {start: 0};
            me.store.baseParams = me.store.baseParams || {};
            me.store.baseParams[me.paramName] = v;
            me.store.reload({params:o});
            me.hasSearch = true;
            me.triggers[0].show();
        }
    });

})();


Ext.override(Ext.Window, {
    constrain: true
//    initEvents: Ext.Window.prototype.initEvents.createSequence(function(){
//        if(this.resizable && this.constrain){
//            this.resizer.constrainTo = this.container;
//        }
//    })
});


(function(){
    Ext.QuickTip.prototype.tagConfig.url = 'qurl';

	Ext.override(Ext.QuickTip, {
        // private
        urlBodyUpdate: function(t){
            var u,
                url,
                et = Ext.fly(t.el),
                cfg = this.tagConfig,
                ns = cfg.namespace;
            url = et.getAttribute(cfg.url, ns);
            if(url){
                u = this.body.getUpdater();
                u.update({
                    scope: this,
                    url: url,
                    callback: function(el, success, response, options){
                        if(success && (et = Ext.fly(t.el))){
                            // found the element again, is changed when move fast through elements
                            var o = {};
                            o[ns+':'+cfg.attribute] = response.responseText; // set
                            o[ns+':'+cfg.url] = ''; // remove qurl to not be loaded many times
                            et.set(o);
                            if(!t.width){
                                this.doAutoWidth();
                            }
                        }
                    }
                });
            }
        },

        showAt: Ext.QuickTip.prototype.showAt.createSequence(function(xy){
            var t = this.activeTarget;
            if(t){
                this.urlBodyUpdate(t);
            }
        })
    });
})();


/**
 * @class Ext.form.VTypes
 * @extends Ext.form.VTypes
 */
Ext.apply(Ext.form.VTypes, {
    password : function(val, field) {
        if (field.initialPassField) {
            var pwd = Ext.getCmp(field.initialPassField);
            return (val == pwd.getValue());
        }
        return true;
    },
    passwordText : i18n.passNotMatch
});

Ext.override(Ext.ColorPalette, {
    allowReselect: true
});

Bible.getI18n = function(key){
    return (i18n[key] ? i18n[key] : key);
};
/**
 * @class Bible.util.Format
 * Reusable data formatting functions
 * @singleton
 */
Bible.util.Format = function(){

    var BORDER  = "border",
        LEFT    = "-left",
        RIGHT   = "-right",
        TOP     = "-top",
        BOTTOM  = "-bottom",
        WIDTH   = "-width",
        STYLE   = "-style",
        COLOR   = "-color",
        BORDERS = [TOP, RIGHT, BOTTOM, LEFT],
        cssRe   = /([a-z0-9-]+)\s*:\s*([^;\s]+(?:\s*[^;\s]+)*);?/gi,
        borderRe   = /([0-9-]+)px\s([a-z]+)\s([#a-f0-9]+)/gi,
        borderWidthRe   = /border-([a-z]+)-width/gi,
        colorRe   = /([a-z-]+)-color/gi,
		keywordSpanTpl = new Ext.XTemplate('<span class="keyword {cls}" style="{style}">'),
		keywordTextTpl = new Ext.XTemplate('<span class="keyword {cls}" style="{style}">{text}</span>');


    function divideBorders(styles){
        var border = styles[BORDER];
        // divide border: in 4
        if(border){
            styles[BORDER + TOP]    = border;
            styles[BORDER + RIGHT]  = border;
            styles[BORDER + BOTTOM] = border;
            styles[BORDER + LEFT]   = border;
            delete styles[BORDER];
        }

        // divide border-XXX in 3
        Ext.each(BORDERS, function(position){
            border = styles[BORDER + position];
            if(border){
                borderRe.lastIndex = 0;
                var matches = borderRe.exec(border);
                ////--console.debug(matches[1],' : ',matches[2],' : ',matches[3]);
                styles[BORDER + position + WIDTH] = matches[1];
                styles[BORDER + position + STYLE] = matches[2];
                styles[BORDER + position + COLOR] = matches[3];
                delete styles[BORDER + position];
            }
        });
    }

    function combineBorders(styles){
        var borderWidth,
            allBorders;

        // combine in border-XXX
        Ext.each(BORDERS, function(position){
            borderWidth = styles[BORDER + position + WIDTH];
            if(borderWidth && borderWidth != '0px'){
                styles[BORDER + position] = String.format("{0} {1} {2}", borderWidth,
                        styles[BORDER + position + STYLE],
                        styles[BORDER + position + COLOR] || 'FFFFFF');
            }
            delete styles[BORDER + position + WIDTH];
            delete styles[BORDER + position + STYLE];
            delete styles[BORDER + position + COLOR];
        });

        // combine 4 border in 1
        allBorders = styles[BORDER + TOP];
        if(allBorders &&
                allBorders == styles[BORDER + RIGHT] &&
                allBorders == styles[BORDER + BOTTOM] &&
                allBorders == styles[BORDER + LEFT]){
            styles[BORDER] = allBorders;
            delete styles[BORDER + TOP];
            delete styles[BORDER + RIGHT];
            delete styles[BORDER + BOTTOM];
            delete styles[BORDER + LEFT];
        }
        return styles;
    }

    return {

        /**
         *
         * @param {String} style
         * @param {Boolean} minimized optional
         */
        getStyleAsObject: function(style, minimized){
            var matches,
                styles = {};

            ////--console.debug('getStyleAsObject', style, minimized);

            // divide style String in styles Object
            cssRe.lastIndex = 0;
            while ((matches = cssRe.exec(style))) {
                ////--console.debug(matches[1], ' : ', matches[1], '  :   ',matches[2]);
                styles[matches[1]] = matches[2];
            }

            ////--console.debug('===== convert style from String to Object =====');
            ////--console.dir(styles);
            if(!minimized){
                ////--console.debug('===== divide border-XXX in 3 =====');
                divideBorders(styles);
                ////--console.dir(styles);
            }

            return styles;
        },

        /**
         *
         * @param {Object/JSON} styles
         * @param {Boolean} minimized optional
         */
        getStyleAsString: function(styles, minimized){
            var style = '';

            ////--console.debug('getStyleAsString', styles, minimized);
            this.normalizeStyles(styles);

            ////--console.dir(styles);
            if(minimized){
                combineBorders(styles);
                ////--console.debug('===== divide border-XXX in 3 =====');
                ////--console.dir(styles);
            }

            // convert object to string
            Ext.iterate(styles, function(key, value) {
                if(value != ''){
                    style += String.format("{0}: {1}; ", key, value);
                }
            }, this);

            return style;
        },

        /**
         * add px at the end of -width elements
         * add # at the beginning of -width elements
         * @param {Object} styles
         */
        normalizeStyles: function(styles){
            Ext.iterate(styles, function(key, value) {
                if(value != ''){
                    if(key.match(borderWidthRe)){
                        styles[key] = value + 'px';
                    } else if(key.match(colorRe)){
                        styles[key] = '#' + value;
                    }
                } else {
                    delete styles[key];
                }
            }, this);
            return styles;
        },

        /**
         * @param {String} style
         * @param {String} cls
         * @return {String} span begin tag with class="keyword {cls}", style="{style}". no text inside
         */
        keywordSpan: function(style, cls){
            return (keywordSpanTpl.apply({
                cls: cls,
                style: style
            }));
        },

        /**
         * @param {String} text
         * @param {String} style
         * @param {String} cls
         * @return {String} span with class="keyword {cls}", style="{style}" and text inside
         */
        keywordText: function(text, style, cls){
            return (keywordTextTpl.apply({
                cls: cls,
                style: style,
                text: text
            }));
            //return String.format('<span class="keyword {0}" style="{1}">{2}</span>', cls, style, text);
        },

        /**
         * Return a string with ... at the end, such as the size is less than maxWidth,
         * when applying the styles of container container.
         * @param {String} str
         * @param {Number} maxWidth
         * @param {Ext.Container} container
         * @return {String}
         */
        ellipsis: function(str, maxWidth, container){
            var c = container ? container : Ext.getBody(),
                elWidth = Ext.util.TextMetrics.measure(c, str).width;
            while(elWidth > maxWidth){
                str = Ext.util.Format.ellipsis(str, str.length-1);
                elWidth = Ext.util.TextMetrics.measure(c, str).width;
            }
            return str;
        }
    }
}();(function(){
    var WORD_BEFORE_REG = /([\s\("])/g,
        WORD_AFTER_REG  = /([\s\.\?\!\)\:,;"])/g,
		KEYWORDS_SEPARATOR = /[\s]*[,]+[\s]*/,
        WORDS_SEPARATOR = /[\s\.\?\!\)\:;\"]+/,
		HIGHLIGHTS_SEPARATOR_REG = /[\s\("\.\?\!\)\:,;\"]+/g;

    String.prototype.insert = function (index, string) {
        if (index > 0) {
            return this.substring(0, index) + string + this.substring(index, this.length);
        } else {
            return string + this;
        }
    };

    function addTerm(matches, term, termMatch, offset){
        var added= false,
            overlap = false,
            item,
            i = 0, l = matches.length;
        // //--console.debug('addTerm', termMatch, offset, matches.length, matches);

        while(i < l && !overlap){
            if(offset >= matches[i].start && offset <= matches[i].end){
                // //--console.debug('overlap', offset, termMatch, i, matches[i], term);
                overlap = true;
            }
            i++;
        }
        item = {
            start: offset,
            end: offset + termMatch.length,
            text: termMatch,
            term: term
        };
        if(overlap){
            // don't allow overlap if preview term was not a word
			if(term.words == 0 && matches[i-1].term.words != 0){
                ////--console.debug('add match %d childs', i);
                matches[i-1].childs = matches[i-1].childs || [];
                matches[i-1].childs.push(item);
                added = true;
            }
        } else {
            matches.push(item);
            added = true;
        }
        return added;
    }

    Ext.util.Terminology = {
        FORMAT_END    : '</span>',
		
		getHighlightsSeparator: function(){
			return HIGHLIGHTS_SEPARATOR_REG;
		},
		
		createHighlightsTerms: function(text, minChars, split){
			var j,
				highlights = [],
				terms = [],
				segments = split ? text.split(HIGHLIGHTS_SEPARATOR_REG) : [text];
			segments.sort(function (a, b) {
                return b.length - a.length;
            });
			for(j=0; j<segments.length; j++) {
				if(segments[j].length < minChars){
					continue;
				}
				// TODO decuple make it based on language
				highlights.push(Bible.escapeDiacriticsRe(Ext.escapeRe(segments[j])));
			}
			if(highlights.length){
				terms.push({
					replaceReg: new RegExp(highlights.join('|'), 'gi'),
					words: 0,
					format: '<span class="termshighlight">'
				});
			}
			//--console.debug('created highlight terms', terms);
			
			return {
				segments: segments,
				terms: terms
			};
		},
		
		createTerms: function(store){
            var terms = [];
            store.each(function(r){
                var k = r.get('keywords'),
                    id = r.get('id'),
					wordsCount,
                    keys = {},
                    format = Bible.util.Format.keywordSpan(r.get('style'), r.get('cls'));
                k = k.split(KEYWORDS_SEPARATOR);

                Ext.each(k, function(e){
                    if(e != ''){
                        wordsCount = e.split(WORDS_SEPARATOR).length;
                        e = Ext.escapeRe(e);
                        if(!keys[wordsCount]){// create array if doesn't exist
                            keys[wordsCount] = [];
                        }
                        keys[wordsCount].push(e);
                    }
                });

                Ext.iterate(keys, function(wordsCount, words){
					words.sort(function (a, b) {
						return b.length - a.length;
					});
                    terms.push({
                        id: id,
                        replaceReg: new RegExp(words.join('|'), 'g'),
                        words: wordsCount,
                        format: format
                    });
                });
            });

            // sort terms based on number of words that they contains
            terms.sort(function (a, b) {
                return b.words - a.words;
            });
			return terms;
        },

        getMatches: function(text, terms){
            var matches = [],
                term,
                len = text.length;

            function termsHighlight(fullMatch, offset, original){
                var endOffset = offset + fullMatch.length;
                ////--console.debug('termsHighlight', arguments, endOffset);
                if (((offset == 0 || original[offset - 1].match(WORD_BEFORE_REG)) &&
                    (endOffset == len || original[endOffset].match(WORD_AFTER_REG))) || term.words == 0) {
                    addTerm(matches, term, fullMatch, offset);
                }
				/*_logger_block_start
				else {
					////--console.debug("don't add term", term, fullMatch, offset, endOffset);
					////--console.debug('after letter', offset>0 ? original[offset - 1]:'',':', original[endOffset]);
				}
				_logger_block_end*/

                return fullMatch;
            }

            Ext.each(terms, function(e){
                term = e;
                text.replace(e.replaceReg, termsHighlight);
            });

            matches.sort(function (a, b) {
                return b.start - a.start;
            });
            ////--console.debug('matches', matches);
            return matches;
        },

        markup: function(text, matches){
            ////--console.debug('matches', matches);
            Ext.each(matches, function(e, i){
                ////--console.debug('markup', e);
                text = text.insert(e.end, Ext.util.Terminology.FORMAT_END);
                if(e.childs){
                    var subTerm = e.childs[0];
                    ////--console.debug('childs terms', e.childs);
                    text = text.insert(subTerm.end, Ext.util.Terminology.FORMAT_END);
                    text = text.insert(subTerm.start, subTerm.term.format);
                }
                text = text.insert(e.start, e.term.format);
            });
            return text;
        },

        highlight: function(text, terms){
            var matches = Ext.util.Terminology.getMatches(text, terms),
                newText = Ext.util.Terminology.markup(text, matches);
            return {
                text: newText,
                matches: matches
            };
        }
    };

    // test
// var terms = Bible.data.KeywordsStore.keywordsReplace;
// var text = "credinţa în Hristos Isus.";
// //--console.dir(Ext.util.Terminology.highlight(text, terms));

})();
(function(){
    /**
     * @class Bible.EventManager
     * @extends Ext.util.Observable
     * @singleton
     */
    var EventManager = Ext.extend(Ext.util.Observable, {
        constructor: function(config){

            this.addEvents(
                /**
                 *@event versechange
                 */
                'versechange',

                /**
                 *@event login
                 */
                'login',

                /**
                 *@event logout
                 */
                'logout'
            );

            // Copy configured listeners into *this* object so that the base class's
            // constructor will add them.
            // this.listeners = config.listeners;

            // Call our superclass constructor to complete construction process.
            EventManager.superclass.constructor.call(this, config)
        }
    });

    Bible.EventManager = new EventManager();
})();/**
 * @class Bible.data.BibleBooksArrayStore
 * @extends Ext.data.ArrayStore
 */
Bible.data.BibleBooksArrayStore = Ext.extend(Ext.data.ArrayStore, {
    constructor: function(config){
        config = config || {};
        Ext.applyIf(config, {
            fields: [
                {name: 'id', type: 'int'},
                'name',
                {name: 'chapters', type: 'int'},
                'lastLoaded'
//                ,
//                {
//                    name: 'order', type: 'int',
//                    convert: function(v, record){
//                        var id = record[0],
//                            total = 66,
//                            cols = 3,
//                            nrPerCol = total / cols,
//                            col = Math.ceil(id / nrPerCol) - 1;
//                        return (id - nrPerCol * col) * cols - (2 - col);
//                    }
//                }
            ],
//            sortInfo: {
//                field: 'order',
//                direction: 'ASC'
//            },
            idIndex: 0,
            data : Bible.records.books
        });
        Bible.data.BibleBooksArrayStore.superclass.constructor.call(this, config);
    }
});
/**
 * @class Bible.data.BibleSearchStore
 * @extends Ext.data.ArrayStore
 */
Bible.data.BibleSearchStore = Ext.extend(Ext.data.Store, {
    constructor: function(config){
        config = config || {};
		var newObjDs = Ext.data.Record.create([
			{name: 'id', type: 'int'},
			{name: 'bnumber', type: 'int'},
			{name: 'cnumber', type: 'int'},
			{name: 'vnumber', type: 'int'},
			{name: 'text', type: 'string'},
			{
				name: 'verse',
				type: 'string',
				convert: function(v, r){
					var verse = Bible.records.books[r[1]-1][1] + ' ' + r[2]+':'+ r[3];
					return verse;
				}
		   }
		]);
		
		Ext.applyIf(config, {
			proxy: new Ext.data.HttpProxy(new Ext.data.Connection({
				method: 'GET',
				url: 'servlets/chapters.php'
				//autoAbort: true
			})),
			baseParams: {
				type: 'all',
				book: '',
				action: 'search',
				limit: 10
			},
			remoteSort: true,
			reader: new Ext.data.ArrayReader({
				totalProperty: 'total',
				root: 'data',
				idIndex: 0
			}, newObjDs),
			sortInfo: {
				field: 'id',
				direction: 'ASC'
			}
        });
        Bible.data.BibleSearchStore.superclass.constructor.call(this, config);
    }
});
(function(){

    /**
     * @class Bible.CrudPlugin
     * @extends Object
     */
	var CrudPlugin = Ext.extend(Object, {
        /**
         * @cfg {Ext.grid.GridPanel} grid
         */
        /**
         * @cfg {Ext.form.FormPanel} form
         */
        /**
         * @cfg {Ext.Button} newButton
         */
        /**
         * @cfg {Ext.Button} saveButton
         */
        /**
         * @cfg {Ext.Button} cancelButton
         */
        disableNewClickEvent: false,
        /**
         * @cfg {Ext.Button} deleteButton optional
         */
        /**
         * @cfg {Boolean} pauseChangeEvents stop onChange function when loading/clearing form
         * (defaults to <tt>true</tt>)
         */
        pauseChangeEvents: false,

        /**
         * @cfg {Boolean} initOnlyCrudFields Defaults to false.
         */
        initOnlyCrudFields: false,

        isNew: false,

		constructor: function(config){
			Ext.apply(this, config);
		},

		init: function(comp){
            var me = this;
            me.comp = comp;

            Ext.applyIf(me.form, {
                setValues: function(value){
                    return me.setValues(value);
                },
                getOriginalValue: function(){
                    return me.originalValue;
                },
                getPauseChangeEvents: function(){
                    //--console.debug('this.comp.getPauseChangeEvents');
                    return me.getPauseChangeEvents();
                },
                setPauseChangeEvents: function(pause){
                    //--console.debug('this.comp.setPauseChangeEvents');
                    return me.setPauseChangeEvents(pause);
                },
                showMask: function(){
                    this.setDisabled(true);
                },
                hideMask: function(){
                    this.setDisabled(false);
                }
            });

            me.comp.addEvents(
                /**
                 * @event validate
                 */
                'validate',
                /**
                 * @event itemselect
                 */
                'itemselect'
                );

			me.initEvents();

            me.changeButtonsState(false, true);
		},

        // private
        initEvents: function(){
            var me = this;

            ////--console.debug('initEvents');
            me.grid.getSelectionModel().on({
                scope: me,
				clearselections: me.onRowDeselect,
                rowselect: me.onRowSelect
			});

            me.form.on({
                scope: me,
                afterrender: me.formAfterRender
            });

			me.saveButton.on('click', me.onSave, me);
            me.cancelButton.on('click', me.onCancel, me);

            if (!me.disableNewClickEvent){
			    me.newButton.on('click', me.onNew, me);
            }
            if(me.deleteButton){
                me.deleteButton.on('click', me.onDelete, me);
                me.deleteButton.setDisabled(true); // initial disable
            }

            me.comp.onCancelButton = function(){
                me.onCancel();
            };
            me.comp.onNewButton = function(){
                me.onNew();
            };
            me.comp.isComponentValid = function(){
                me.isValid();
            };

            me.initItemsEvents(me.form.items);
            // verify if form is crudField
            if(me.initOnlyCrudFields && me.form.crudField){
                me.addItemEvents(me.form);
            }
        },

        /**
         * shortcut, fire event for this.component
         */
        fireEvent: function(){
            return this.comp.fireEvent.apply(this.comp, arguments);
        },

        formAfterRender: function(){
            var me = this;
            me.initValue();
            ////--console.debug('form afterrender. selections: ', this.grid.getSelectionModel().hasSelection(), ', isNew: ', this.isNew);
            if(!me.isNew && !me.grid.getSelectionModel().hasSelection()){
                me.form.setDisabled(true);
            }
        },

        // private
		initItemsEvents: function(items){
            ////--console.debug('initItemsEvents');
			items.each(function(item){
                if (item.isComposite || item.getXType() == 'fieldset'){
                    if (Ext.isArray(item.items)){
                        for(var i = 0, len = item.items.length; i < len; i++){
                            this.initItemEvents(item.items[i]);
                        }
                    } else {
                        //mixed collection
                        item.items.each(function(item){
                            this.initItemEvents(item);
                        }, this)
                    }
                } else {
                    this.initItemEvents(item);
                }
			}, this);
		},

        // private
        initItemEvents: function(item){
//            //--console.debug('initItemEvents', item.name);
            if (item.items){
                if(item.crudField){
                    this.addItemEvents(item);
                }
                this.initItemsEvents(item.items);
            } else if(item.crudField || (!this.initOnlyCrudFields && Ext.form.FormPanel.prototype.isField(item))){
                this.addItemEvents(item);
            }
        },

        // private
        addItemEvents: function(item){
            var me = this;
            item.on('keyup', me.onChange, me);
            item.on('change', me.onChange, me);
            //if(item.getXType() == 'combo'){
                item.on("select", me.onChange, me);
            //}
            if(item.getXType() == 'checkbox'){
                item.on("check", me.onChange, me);
            }
            if(item.getXType() == 'spinnerfield'){
                item.on("spin", me.onChange, me);
            }
        },

        // private
		onRowSelect: function(sm, index, r){
            var me = this;
            ////--console.debug('onRowSelect');
            me.setIsNew(false);
            me.form.setDisabled(false);
            me.changeButtonsState(false, true);
            if(me.deleteButton){
                me.deleteButton.setDisabled(false);
            }

            //this.setPauseChangeEvents(true);
            // TODO use 2 lines to setValues on form
            //this.fireEvent('itemselect', sm, index, r);
            // must call form.setValues(values) in on.itemselect ;
            //this.setPauseChangeEvents(false);
		},

        // private
        setValues: function(value){
            //--console.debug('Crud: setValues:', value);
            if(this.form.getForm){
                this.form.getForm().setValues(value);
            }
            this.initValue(value);
        },

		onRowDeselect: function(sm, index, r){
            ////--console.debug('onRowDeselect');
            var me = this;
            if(!me.isNew){
                me.form.setDisabled(true);
            }
            me.doReset();
            if(me.deleteButton){
                me.deleteButton.setDisabled(true);
            }
		},

        doReset: function(){
            if(this.form.getForm){
                this.form.getForm().reset();
            }
        },

        onSave: function(item, response){
            var me = this;
            me.setIsNew(false);
            me.changeButtonsState(false, true);
            me.grid.setDisabled(false);
            me.initValue();
        },

        /**
         * @param {Boolean} isNew
         */
        setIsNew: function(isNew){
            var me = this;
            me.isNew = isNew;
            me.comp.isNew = isNew;
            me.form.isNew = isNew;
            me.newButton.setDisabled(isNew);
        },

        onNew: function(){
            var me = this;
            //--console.debug('onNew');
			me.setIsNew(true);

			me.grid.getSelectionModel().clearSelections();
            me.grid.setDisabled(true);

			me.changeButtonsState(true, false);
            me.form.setDisabled(false);
            me.fireEvent('newitem');
		},

        onDelete: function(){
            //--console.debug('TODO onDelete');
        },

		onCancel: function(){
            ////--console.debug('onCancel');
			var me = this,
                record,
                isNew = me.isNew;

            if (isNew){
                //--console.debug('onCancel new object');
                me.doReset();
                me.form.setDisabled(true);
                me.grid.setDisabled(false);
            } else if(record = me.grid.getSelectionModel().getSelected()){
                me.setValues(me.originalValue);
            }
            me.setIsNew(false);
            me.changeButtonsState(false, true);
		},

        /**
         * @return {Boolean} pauseChangeEvents
         */
        getPauseChangeEvents: function(){
            return this.pauseChangeEvents;
        },

        /**
         * @param {Boolean} pause
         */
        setPauseChangeEvents: function(pause){
            this.pauseChangeEvents = pause;
        },

		isChanged: function(){
            if (!this.grid.getSelectionModel().getSelected()){
                ////--console.debug('isChanged (not selected)', false);
                return false;
            }

            var changes = !Bible.deepEquals(this.getValues(), this.originalValue);
            //--console.debug('isChanged', changes);
            ////--console.dir(this.originalValue);
            ////--console.dir(this.getValues());
			return changes;
		},

        /**
         * @param {Boolean} changes
         * @param {Boolean} valid
         */
        changeButtonsState: function(changes, valid){
            //--console.debug('changeButtonsState(changes, valid)',changes, valid);
            this.saveButton.setDisabled(!valid || !changes);
            this.cancelButton.setDisabled(!changes);
        },

        onChange: function(){
            this.fireEvent("formchanged");
//            //--console.debug('onChange');
            if(!this.getPauseChangeEvents()){
                this.adjustButtons();
            }
        },

		adjustButtons: function(){
            //--console.debug('adjustButtons');
			var valid,
                changed;

            changed = this.isNew || this.isChanged();
            if (changed){
                valid = this.isValid();
            }

            this.changeButtonsState(changed, valid);
		},

        isValid: function(){
            ////--console.debug('isValid');
            var valid = false;

            if (this.form.getForm){
                valid = this.form.getForm().isValid();
            } else {
                valid = true; // otherwise valid will remain always false
            }

            valid = valid && (this.fireEvent("validate") !== false);
            ////--console.debug('isValid', valid);
            return valid;
        },

        initValue: function(value){
            var formValue = this.getValues();
            /**
             * @type {Object}
             * @property originalValue
             */
            //this.originalValue = Bible.deepCloneObject(formValue);
            //TODO must use values for better perf - see why deepClone?
            //this.originalValue = value || this.getValues();
            this.originalValue = this.getValues();
        },

        getValues: function(){
            //return this.form.getForm().getFieldValues();
            return this.form.getForm().getValues();
        }
	});

	Bible.CrudPlugin = CrudPlugin;
})();/**
 * @class Bible.plugins.TabPanelAddButton
 * @extends Object
 */
Bible.plugins.TabPanelAddButton = Ext.extend(Object, {
    /**
     * @cfg {Number} maxLimit
     */
    maxLimit: 10,
    /**
     * @cfg {Ext.Button} addButton
     */

    constructor: function(cfg) {
        //--console.debug(cfg);
        Ext.apply(this, cfg || {});
        //Bible.plugins.TabPanelAddButton.superclass.constructor.call(this, cfg);
    },

    init: function(tabPanel){
        var me = this;
        me.tabPanel = tabPanel;

        tabPanel.afterMethod('onRemove', me.onRemove, me);
        tabPanel.afterMethod('onAdd', me.onAdd, me);
        tabPanel.afterMethod('delegateUpdates', me.delegateUpdates, me);
    },

    // private
    createAddButton : function(){
        var me = this,
            tabPanel = me.tabPanel,
            h = tabPanel.stripWrap.dom.offsetHeight,
            sr = tabPanel.pos.insertFirst({
                cls:'x-tab-left-btn-new-tab x-toolbar'
            });
        tabPanel.pos.addClass('x-tab-scrolling');

        //--console.debug('createAddButton');
        me.addButton.render(sr);
        sr.setHeight(h);
        me.btnAddTabContainer = sr;
    },

//    onAdd: Ext.TabPanel.prototype.onAdd.createSequence(function() {
    onAdd: function() {
        //--console.debug('onAdd');
        if(this.tabPanel.items.getCount() > this.maxLimit-1){
            this.addButton.setDisabled(true);
        }
    },
//    onRemove: Ext.TabPanel.prototype.onRemove.createSequence(function() {
    onRemove: function() {
        if(this.tabPanel.items.getCount() < this.maxLimit){
            this.addButton.setDisabled(false);
        }
    },
//    delegateUpdates: Ext.TabPanel.prototype.delegateUpdates.createSequence(function() {
    delegateUpdates: function() {
        var me = this,
            tabPanel = me.tabPanel,
            btnAddTabContainer = me.btnAddTabContainer;
        if(tabPanel.pos){
            if(!btnAddTabContainer){
                me.createAddButton();
            } else {
                if(tabPanel.scrolling){
                    tabPanel.stripWrap.setStyle('marginLeft', 53 + 'px');
                    btnAddTabContainer.setLeft(18);
                } else {
                    tabPanel.stripWrap.setStyle('marginLeft', 35 + 'px');
                    btnAddTabContainer.setLeft(0);
                    tabPanel.pos.addClass('x-tab-scrolling');
                }
            }
        }
        // TODO when add new tab scroll, (wrap width - btnAddTab.width)
    }
});/**
 * @class Bible.NavigationToolbar
 * @extends Ext.Toolbar
 * @constructor Create a new NavigationToolbar
 * @param {Object} config The config object
 * @xtype navigationtoolbar
 */
(function() {

var T = Ext.Toolbar;

Bible.NavigationToolbar = Ext.extend(Ext.Toolbar, {
    /**
     * @cfg {Boolean} prependButtons
     * <tt>true</tt> to insert any configured <tt>items</tt> <i>before</i> the paging buttons.
     * Defaults to <tt>false</tt>.
     */
    /**
     * @cfg {String} firstText
     * The quicktip text displayed for the first page button (defaults to <tt>'Primul Capitol'</tt>).
     * <b>Note</b>: quick tips must be initialized for the quicktip to show.
     */
    firstText : 'Primul Capitol',
    /**
     * @cfg {String} prevText
     * The quicktip text displayed for the previous page button (defaults to <tt>'Previous Page'</tt>).
     * <b>Note</b>: quick tips must be initialized for the quicktip to show.
     */
    prevText : 'Capitolul Anterior (CTRL + Stânga)',
    /**
     * @cfg {String} nextText
     * The quicktip text displayed for the next page button (defaults to <tt>'Next Page'</tt>).
     * <b>Note</b>: quick tips must be initialized for the quicktip to show.
     */
    nextText : 'Următorul Capitol (CTRL + Dreapta)',
    /**
     * @cfg {String} lastText
     * The quicktip text displayed for the last page button (defaults to <tt>'Last Page'</tt>).
     * <b>Note</b>: quick tips must be initialized for the quicktip to show.
     */
    lastText : 'Ultimul Capitol',

    initComponent : function(){
        var me = this,
            pagingItems = [
                me.first = new T.Button({
                    tooltip: me.firstText,
                    overflowText: me.firstText,
                    iconCls: 'x-tbar-page-first',
                    handler: me.moveFirst,
                    scope: me
                }), me.prev = new T.Button({
                    tooltip: me.prevText,
                    overflowText: me.prevText,
                    iconCls: 'x-tbar-page-prev',
                    handler: me.movePrevious,
                    scope: me
                }),
                me.next = new T.Button({
                    tooltip: me.nextText,
                    overflowText: me.nextText,
                    iconCls: 'x-tbar-page-next',
                    handler: me.moveNext,
                    scope: me
                }), me.last = new T.Button({
                    tooltip: me.lastText,
                    overflowText: me.lastText,
                    iconCls: 'x-tbar-page-last',
                    handler: me.moveLast,
                    scope: me
                })
            ],
            userItems = me.items || me.buttons || [];
        if (me.prependButtons) {
            me.items = userItems.concat(pagingItems);
        }else{
            me.items = pagingItems.concat(userItems);
        }
        delete me.buttons;
        if(deviceType != 'mobile'){
            me.defaults = {
                scale: 'medium'
            };
        }
        Bible.NavigationToolbar.superclass.initComponent.call(me);

        me.bindStore(me.store, true);
    },

    bindStore : function(store, initial){
        var me = this;
        me.mon(store, 'load', function(s, r, o){
            var b = o.params.book,
                c = o.params.chapter,
                maxC = me.grid.booksStore.getById(b).get('chapters');
            me.first.setDisabled(b == 1 && c == 1);
            me.prev.setDisabled(b == 1 && c == 1);
            me.next.setDisabled(b == 66 && c == maxC);
            me.last.setDisabled(b == 66 && c == maxC);
        }, me);
    },
	
    // private
    getPageData : function(){
        return {
            book: this.grid.booksCombo.getValue(),
			chapter: this.grid.chaptersCombo.getValue()
        };
    },
	
    // private
    doLoad : function(params){
        this.grid.setPage(params, 1);
    },

    /**
     * Move to the first page, has the same effect as clicking the 'first' button.
     */
    moveFirst : function(){
        var o = this.getPageData();
		if (o.chapter > 1) {
			o.chapter = 1;
		} else if(o.book > 1){
			o.book--;
			o.chapter = this.grid.booksStore.getById(o.book).get('chapters');
		}
		this.doLoad(o);
    },

    /**
     * Move to the previous page, has the same effect as clicking the 'previous' button.
     */
    movePrevious : function(){
        var o = this.getPageData();
		if (o.chapter > 1) {
			o.chapter--;
		} else if(o.book > 1){
			o.book--;
			o.chapter = this.grid.booksStore.getById(o.book).get('chapters');		
		}
		this.doLoad(o);
    },

    /**
     * Move to the next page, has the same effect as clicking the 'next' button.
     */
    moveNext : function(){
        var o = this.getPageData(),
			record = this.grid.booksStore.getById(o.book);
		if (o.chapter < record.get('chapters')) {
			o.chapter++;
		} else if(o.book < 66){
			o.book++;
			o.chapter = 1;
		}
		this.doLoad(o);
    },

    /**
     * Move to the last page, has the same effect as clicking the 'last' button.
     */
    moveLast : function(){
		var o = this.getPageData(),
			record = this.grid.booksStore.getById(o.book),
            chapters = record.get('chapters');
		if (o.chapter < chapters) {
			o.chapter = chapters;
		} else if(o.book < 66){
			o.book++;
			o.chapter = 1;
		}
		this.doLoad(o);
    }
});

    Ext.reg('navigationtoolbar', Bible.NavigationToolbar);

})();
/**
 * @class Bible.form.SearchFieldLocal
 * @extends Ext.form.TwinTriggerField
 * <pre><code>var searchFieldLocal = new Bible.form.SearchFieldLocal({
    store: ds,
    onKeyup: true,
    emptyText: '...',
    filterByFields: ['name', 'title', {name:'modifiedDate', type:'date', dateFormat: strDateTimeFormat}]
});</code></pre>
 * @author Matei Nicolae
 */
Bible.form.SearchFieldLocal = Ext.extend(Ext.form.TwinTriggerField,{
    /**
     * @cfg {Array}
     */
    filterByFields: [],
    /**
     * @cfg {Ext.form.Checkbox} checkFilter
     */
    validationEvent:false,
    validateOnBlur:false,
    trigger1Class:'x-form-clear-trigger',
    trigger2Class:'x-form-search-trigger',
    trigger1Qtip: false,
    trigger2Qtip: false,
    hideTrigger1:true,
    hideTrigger2:false,
    hasSearch : false,
    width: 150,
	emptyText: '',
	onKeyup: true,
	filterCombos: false, // New property
    minChars: 2,

    initComponent : function(){
        var me = this;
        Bible.form.SearchFieldLocal.superclass.initComponent.call(me);
        if(me.trigger1Qtip){
            me.triggerConfig.cn[0]['ext:qtip'] = me.trigger1Qtip;
        }
        if(me.trigger2Qtip){
            me.triggerConfig.cn[1]['ext:qtip'] = me.trigger2Qtip;
        }
		me.highlightsTerms = [];
    },

    initEvents : function(){
        var me = this;
		Bible.form.SearchFieldLocal.superclass.initEvents.call(me);
		me.on({
            scope: me,
            specialkey: function(f, e){
                if(e.getKey() == e.ENTER){
                    this.onTrigger2Click();
                }
            }
        });
        if(me.onKeyup) {
            me.el.on('keyup', me.onTrigger2Click, me);
        }

        if(me.checkFilter){
            //this.mon(this.checkFilter, 'check', function(){
            me.mon(me.checkFilter, 'toggle', function(){
				me.onTrigger2Click();
            }, me);

            me.mon(me.store, 'load', function(){
                if(me.checkFilter.pressed){
                    me.onTrigger2Click();
                }
            }, me);
        }
    },

    setValue : function(v){
		Bible.form.SearchFieldLocal.superclass.setValue.apply(this, arguments);
        if(v.length < this.minChars){
            this.onTrigger1Click();
        } else {
            this.onTrigger2Click();
        }
    },

    /**
     * The function that should handle the trigger's click event.  This method does nothing by default
     * until overridden by an implementing function. See {@link Ext.form.TriggerField#onTriggerClick}
     * for additional information.
     * @method
     * @param {EventObject} e
     */
    onTrigger1Click : function(){
        var me = this,
            combos,
            j = 0;
		me.highlightsTerms = [];
        if(me.hasSearch){
			me.el.dom.value = '';
            me.triggers[0].hide();
            me.hasSearch = false;
            me.store.filterBy(function(n) {return true;});
//            this.store.clearFilter(false);
			// verify if there are combos that have to filter store
	        if(me.filterCombos){
	        	combos = me.filterCombos;
	            for(; j<combos.length; j++) {
	            	if(combos[j].combo.getValue())
	            		me.store.filter(combos[j].field, combos[j].combo.getValue());
	            }
	        }
			me.focus();
        }
    },

    /**
     * The function that should handle the trigger's click event.  This method does nothing by default
     * until overridden by an implementing function. See {@link Ext.form.TriggerField#onTriggerClick}
     * for additional information.
     * @method
     * @param {EventObject} e
     */
    onTrigger2Click : function(){
        var me = this,
            text = me.getRawValue(),
            notFilter,
            re,
            fields,
            combos,
            w = 0;
		me.highlightsTerms = [];
        if(text.length < me.minChars){
            me.onTrigger1Click();
            return;
        }
        me.hasSearch = true;
        me.triggers[0].show();
		me.focus();
		
		var highlights = Ext.util.Terminology.createHighlightsTerms(text, me.minChars, true);
		re = highlights.segments;
		me.highlightsTerms = highlights.terms;

		fields = me.filterByFields;
        combos = me.filterCombos;
		
		//notFilter = (fields.length == 0) || (this.checkFilter ? !this.checkFilter.getValue() : false);
        notFilter = (fields.length == 0) || (me.checkFilter ? !me.checkFilter.pressed : false);
		
		for(; w<re.length; w++) {
			//re[w] = new RegExp(Ext.escapeRe(re[w]), 'i'); // Any match
			re[w] = new RegExp(Bible.escapeDiacriticsRe(Ext.escapeRe(re[w])), 'i'); // Any match
		}
		
		me.store.isBeforeFilter = true;
		me.store.filterBy(function(r){
			if(notFilter){
                return true;
            }
            var rez,
                i = 0,
                j;
			for(; i<re.length; i++) { // for each word in Filter
                rez = false;
				for(j=0; j<fields.length; j++) { // for each field
					if(typeof fields[j] != 'object') {
						if(re[i].test(r.get( fields[j] ))) {
							rez = true;
							j = fields.length;
						}
					} else {
						if(re[i].test(r.get( fields[j].name ))) {
							rez = true;
							j = fields.length;
						} else if(fields[j].type == 'date') {
							var dFormat = fields[j].dateFormat;
							if(typeof dFormat == 'undefined') dFormat = 'd/m/Y';
							var val = new Date(r.get( fields[j].name )).format(dFormat);
							if(re[i].test(val)) {
								rez = true;
								j = fields.length;
							}
						}
					}
				}
				if(!rez) { // if can't find a word in all Fields
					return false;
				}
			}
			if(combos){
	            for(j=0; j<combos.length; j++) {
	            	if(combos[j].combo.getValue()){
		            	if(combos[j].combo.getValue() != r.get( combos[j].field )) {
							 return false;
						}
	            	}
	            }
	        }
			return true;
		});
		me.store.isBeforeFilter = false;
    }
});

Ext.reg('searchfieldlocal', Bible.form.SearchFieldLocal);




/**
 * @class Bible.form.ComboSearchFieldLocal
 * @extends Ext.form.ComboBox
 * <pre><code>var comboSearchFieldLocal = new Bible.form.ComboSearchFieldLocal({
    store: ds,
    emptyText: AppKeyWords.find,
});</code></pre>
 * @author Matei Nicolae
 */
Bible.form.ComboSearchFieldLocal = Ext.extend(Ext.form.ComboBox,{
    validationEvent:false,
    validateOnBlur:false,
    trigger1Class:'x-form-clear-trigger',
    hideTrigger1:true,
    hideTrigger2:false,
    hasSearch : false,
    emptyText: '',

    initComponent : function(){
		Bible.form.ComboSearchFieldLocal.superclass.initComponent.call(this);
        this.triggerConfig = {
            tag:'span', cls:'x-form-twin-triggers', cn:[
            {tag: "img", src: Ext.BLANK_IMAGE_URL, alt: "", cls: "x-form-trigger " + this.trigger1Class},
            {tag: "img", src: Ext.BLANK_IMAGE_URL, alt: "", cls: "x-form-trigger " + this.trigger2Class}
        ]};

        this.addEvents(
            /**
             * @event clearfilter
             * Fires when the clear trigger is clicked : onTrigger1Click
             * @param {Whitney.form.ComboSearchFieldLocal} this This combo field
             */
            'clearfilter'
        );
    },
    
    initEvents : function(){
		Bible.form.ComboSearchFieldLocal.superclass.initEvents.call(this);

        this.triggers[0].hide();
        
        this.on({
            scope: this,
            select: function(){
                ////--console.debug('ComboSearchFieldLocal select');
                this.onFilter();
            },
            change: function(combo, newValue, oldValue){
                if(newValue == ''){
                    //--console.debug('change to blank -> clearSearch');
                    this.clearSearch();
                }
            }
        });

    },

    initTrigger : Ext.form.TwinTriggerField.prototype.initTrigger,

    getTriggerWidth: Ext.form.TwinTriggerField.prototype.getTriggerWidth,

    onDestroy: Ext.form.TwinTriggerField.prototype.onDestroy,

    /**
     * The function that should handle the trigger's click event.  This method does nothing by default
     * until overridden by an implementing function. See {@link Ext.form.TriggerField#onTriggerClick}
     * for additional information.
     * @method
     * @param {EventObject} e
     */
    onTrigger1Click : function(){
        ////--console.debug('onTrigger1Click');
        this.clearSearch();
    },

    /**
     * The function that should handle the trigger's click event.  This method does nothing by default
     * until overridden by an implementing function. See {@link Ext.form.TriggerField#onTriggerClick}
     * for additional information.
     * @method
     * @param {EventObject} e
     */
    onTrigger2Click : function(){
        ////--console.debug('onTrigger2Click');
        this.onTriggerClick();
    },

    /**
     * 
     */
    clearSearch: function(){
        var me = this;
        ////--console.debug('clearSearch');
        if(me.hasSearch){
            me.triggers[0].hide();
            me.hasSearch = false;
            me.store.clearFilter(false);
            me.reset();
//            this.postBlur();
            me.onBlur();
            me.fireEvent('clearfilter', me);
			//this.el.focus();
        }
    },

    onFilter: function(){
        this.hasSearch = true;
        this.triggers[0].show();
    }
});

Ext.reg('combosearchfieldlocal', Bible.form.ComboSearchFieldLocal);(function(){
	var ADVANCED_SEARCH_REG = /[\s+\.\:]/;

/**
 * @class Bible.form.BibleBooksComboBox
 * @extends Ext.form.ComboBox
 */	
Bible.form.BibleBooksComboBox = Ext.extend(Ext.form.ComboBox, {
    
	infoTooltip: "scrie Cartea, capitolul şi versetul <br/>(ex. <span class='bold'>'Matei 5'</span>, <span class='bold'>'Mat 5.3'</span>, sau <span class='bold'>'Mat 5:3'</span>)",
	
	width: 150,
    displayField:'name',
    valueField: 'id',
    mode: 'local',
    allowBlank: false,
    selectOnFocus: true,
    lastQuery: '',
    lazyInit: false,
    lazyRender: false,
    forceSelection: true,
    //typeAhead: true,
    triggerAction: 'all',
    editable: true,
    listClass: 'x-combo-list-small x-combo-bible-books',
//	listWidth: 412,
//    maxHeight: 440,
    tpl: '<tpl for="."><div class="x-combo-list-item"><div>{id}</div>{name}</div></tpl>',
	
    initComponent : function(){
        if(!this.store){
            //--console.debug('store auto created');
            this.store = new Bible.data.BibleBooksArrayStore();
        }
        Bible.form.BibleBooksComboBox.superclass.initComponent.call(this);
    },
	
	initEvents: function(){
		Bible.form.BibleBooksComboBox.superclass.initEvents.call(this);
		
		if(this.infoTooltip){		
			new Ext.ToolTip({
				target: this.wrap,
				delegate: '.x-form-trigger',
				html: this.infoTooltip,
				anchor: 'br-tr',
				mouseOffset: [-(this.width - 17), 0],
				renderTo: document.body,
				dismissDelay: 8000
			});
		}
	},
	
	doQuery : function(q, forceAll){
        q = Ext.isEmpty(q) ? '' : q;
        var qe = {
            query: q,
            forceAll: forceAll,
            combo: this,
            cancel:false
        };
        if(this.fireEvent('beforequery', qe)===false || qe.cancel){
            return false;
        }
        q = qe.query;
		if(q.length > 1 && q[1] != ' ' && Ext.isNumber(q[0]*1)){
			//--console.debug('insert space after first number', q);
			q = q.insert(1, ' ');
			//--console.debug('new query after space inserted', q);
		}
		var s = q.split(ADVANCED_SEARCH_REG),
			chapter, verse,
			bookExtraParams = false,
			len = s.length,
			startParamIdx = 1;
		//--console.debug('query', q, s);
		if(len > 1){
			if(Ext.isNumber(s[0]*1)){
				q = s[0] + ' ' + s[1];
				//--console.debug('concat values', q);
				startParamIdx = 2;
			} else {
				q = s[0];
			}
			if(len > startParamIdx){
				chapter = Ext.num(parseInt(s[startParamIdx]), 0);
				if(len > startParamIdx + 1){
					verse = Ext.num(parseInt(s[startParamIdx + 1], 0));
				}
			}
			if(chapter){
				bookExtraParams = {
					chapter: chapter,
					verse: verse
				};
			}
			//--console.debug('new query', q);
		}
		this.bookExtraParams = bookExtraParams;
        forceAll = qe.forceAll;
        if(forceAll === true || (q.length >= this.minChars)){
            if(this.lastQuery !== q){
                this.lastQuery = q;
                if(this.mode == 'local'){
                    this.selectedIndex = -1;
                    if(forceAll){
                        this.store.clearFilter();
                    }else{
                        this.store.filter(this.displayField, q, true, false, false);
                    }
                    this.onLoad();
                }else{
                    this.store.baseParams[this.queryParam] = q;
                    this.store.load({
                        params: this.getParams(q)
                    });
                    this.expand();
                }
            }else{
                this.selectedIndex = -1;
                this.onLoad();
            }
        }
    }
});

	Ext.reg('biblebookscombobox', Bible.form.BibleBooksComboBox);

})();
(function(){
    /**
	 * @class Bible.BibleGridPanel
	 * @extends Ext.grid.EditorGridPanel
	 */
	var separator = '.',
        BOOKS_URL = 'servlets/books.php',
        CHAPTERS_URL = 'servlets/chapters.php',
        VERSE_URL = 'servlets/verse.php',

        START_REF_REG_EXP = new RegExp(Ext.escapeRe('#'), 'g'),
        END_REF_REG_EXP = new RegExp(Ext.escapeRe('$'), 'g'),

    BibleGridPanel = Ext.extend(Ext.grid.EditorGridPanel, {
		cls: 'bible-grid',
		hideHeaders: true,
		columnLines: true,
        autoExpandColumn: 'text',
        clicksToEdit: 1,

        /**
         * @cfg {Boolean} autoLoad true to autoLoad store. defaults to true
         */
        autoLoadChapter: true,

		initComponent: function(){
            var me = this,
                hashBook,
                actions = Bible.getActions();
            if(me.hashBook && (hashBook = actions[me.hashBook])){
                var defaultActions = hashBook.split(separator);
                me.defaultBook = Ext.num(parseInt(defaultActions[0]), 1);
                me.defaultChapter = Ext.num(parseInt(defaultActions[1]), 1);
                me.defaultVerse = defaultActions[2]; // TODO make this public
            } else {
                me.defaultBook = 1;
                me.defaultChapter = 1;
            }

			me.chaptersStore = new Ext.data.ArrayStore({
				fields: ['id'],
				data : [[1]]
			});

			// create the data store
            me.store = new Ext.data.ArrayStore({
				showBackgroundColors: true,

                proxy: new Ext.data.HttpProxy(new Ext.data.Connection({
                    method: 'GET',
                    url: CHAPTERS_URL,
					autoAbort: true
				})),
				idIndex: 0,
                root: 'data',
                baseParams: {
					action: 'get_chapter',
					references: Bible.defaults.references,
					titles: Bible.defaults.titles
				},
                fields: [
                    {name: 'id', type: 'int'},
                    {name: 'cnumber', type: 'int'},
                    {name: 'vnumber', type: 'int'},
                    {name: 'text', type: 'string'},
                    {name: 'title', type: 'string'},
                    {name: 'ref', type: 'string'},
                    // user specific changes
                    {name: 'comment', type: 'string'},
                    {name: 'bgcolor', type: 'string'},
                    {name: 'keyverse', type: 'string'}
                ]
			});

			me.checkFilter = new Ext.Button({
                iconCls: 'icon-filter',
				tooltip: i18n.filter,
				enableToggle: true
			});

			// TODO must create termshighlight class only not search
			me.searchField = new Bible.form.SearchFieldLocal({
                emptyText: 'Evidenţiază cuvinte...', // TODO i18n
                trigger2Qtip: 'Caută/Evidenţiază cuvinte în capitolul curent',
				store: me.store,
				filterByFields: ['text'],
                checkFilter: me.checkFilter,
				split: true,
                width: 145
			});
			me.store.searchField = me.searchField;

            me.commentEditor = new Ext.form.TextArea({
				cls: 'comment-editor',
                style: 'padding: 3px 6px',
                //grow: true, // TODO try to implement but ho have boxMinHeight min 60 or row height
                boxMinHeight: 62
            });

            var commentEditor2 = new Ext.grid.GridEditor(me.commentEditor, {
                offsets: [-2, -1]
            });

            var columns = [
                new Ext.grid.RowNumberer({
                    width: 27,
                    dataIndex: 'vnumber',
                    renderer : function(v, p, record){
                        if(this.rowspan){
                            p.cellAttr = 'rowspan="'+this.rowspan+'"';
                        }
                        var title = record.get('title');
                        if(title){
                            v = '<b ext:qtip="'+title+'">'+ v +'</b>';
                        }

                        if(record.get('keyverse')){
                            p.css = 'gold-verse';
                        }
                        return v;
                    }
                }),
                {
                    id:'text',
                    dataIndex: 'text',
                    width: 75,
                    renderer: function(val, metaData, record, rowIndex, colIndex, store){
                        var title,
                            ref,
							highlightText = Bible.highlightTerms(val, store);
                        me.keywordsMatches = me.keywordsMatches.concat(highlightText.matches);
                        if(store.showKeywords){
							val = highlightText.text;
						}
//                        val = '<span class="verse-nr">('+record.get('vnumber')+')</span> ' + val;

                        if(store.baseParams.titles){
                            title = record.get('title');
                            if(title){
                                val = '<div class="title">' +title+ '</div>' + val;
                            }
                        }
                        if(store.baseParams.references){
                            ref = record.get('ref');
                            if(ref){
                                ref = ref.replace(START_REF_REG_EXP,
                                        '<span class="ref" ext:qwidth="200" ext:qtip=" " ext:qurl="' + VERSE_URL + '?id=');
                                ref = ref.replace(END_REF_REG_EXP, '</span>');
                                val += '<div class="references">' +ref+ '</div>';
                            }
                        }
                        if(store.showBackgroundColors && record.get('bgcolor')){
                            metaData.attr = 'style="background-color: #'+ record.get('bgcolor') +';"';
                        }
                        return val;
                    }
                },
                {
                    id:'comments',
                    dataIndex: 'comment',
                    width: 200,
                    fixed: true,
                    hidden: true,
                    renderer: Bible.rendererComments,
                    editor: commentEditor2
                },
                {
                    id: 'comments-img',
                    dataIndex: 'comment',
                    width: 27,
                    fixed: true,
                    hideable: false,
                    menuDisabled: true,
                    renderer: function(v, metaData){
                        if(v){
                            metaData.css = 'comment-knotes';
                        }
                        return '';
                    }
                }
            ];


			Ext.apply(me, {
                keywordsMatches: [],
				viewConfig: {
                    autoFill: true,
					forceFit: true,
//					scrollOffset: 1,
                    templates: {
                        cell: new Ext.XTemplate(
                            '<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style="{style}" tabIndex="0" {cellAttr}>',
                                '<div class="x-grid3-cell-inner x-grid3-col-{id}" <tpl if="id != \'text\'">unselectable="on"</tpl> {attr}>{value}</div>',
                            '</td>'
                        )
                    }
				},
                keys: [
                    {
                        key: Ext.EventObject.RIGHT,
                        ctrl:true,
                        fn: function() {
                            //--console.debug('Ctrl+RIGHT moveNext');
                            me.getBottomToolbar().moveNext();
                        }
                    },
                    {
                        key: Ext.EventObject.LEFT,
                        ctrl:true,
                        fn: function() {
                            //--console.debug('Ctrl+LEFT movePrevious');
                            me.getBottomToolbar().movePrevious();
                        }
                    },
                    {
                        key: Ext.EventObject.PAGE_DOWN,
                        fn: function() {
                            var view = me.view,
                                scroller = view.scroller;
                            //--console.debug('PAGE_DOWN');
//                            //--console.debug('scrollTop, scroller, mainBody',
//                                    scroller.dom.scrollTop, scroller.getHeight(), view.mainBody.getHeight());
//                            //--console.info( 'TOTAL    :', view.mainBody.getHeight() - scroller.getHeight());
                            if((view.mainBody.getHeight() - scroller.getHeight() - scroller.dom.scrollTop) <= 0){
                                //--console.info('PAGE_DOWN moveNext');
                                me.getBottomToolbar().moveNext();
                            }
                        }
                    },
                    {
                        key: Ext.EventObject.PAGE_UP,
                        fn: function() {
                            var view = me.view,
                                scroller = view.scroller;
                            //--console.debug('PAGE_UP');
                            if(scroller.dom.scrollTop == 0){
                                //--console.info('PAGE_UP movePrevious');
                                me.getBottomToolbar().movePrevious();
                            }
                        }
                    },
                    {
                        key: Ext.EventObject.C,
                        shift:true,
                        fn: function(){
                            //--console.debug('Shift + C');
                            me.commentsButton.toggle();
                        }
                    },
					{
                        key: Ext.EventObject.K,
                        shift:true,
                        fn: function(){
                            //--console.debug('Shift + K');
                            me.keywordsButton.toggle();
                        }
                    },
					{
                        key: Ext.EventObject.R,
                        shift:true,
                        fn: function(){
                            //--console.debug('Shift + R');
                            me.referencesButton.toggle();
                        }
                    },
                ],
				sm: new Ext.grid.RowSelectionModel({
					singleSelect: true
				}),
				tbar: new Ext.Container({
                    items: [
                        new Ext.Toolbar({
                            enableOverflow: true, // TODO items are not shown all
                            items: (function(){
								var items = me.getTopToolbarItems();
								items.push(me.getSecondTopToolbarItems());
								return items;
							})()
                        }),
                        me.titleToolbar = new Ext.Toolbar({
                            autoHeight: true,
                            items : [
                                {
                                    xtype: 'spacer',
                                    cls: 'toolbar-icon'
                                },
                                i18n.theme + ' :',
                                me.titleEditor = new Ext.Toolbar.TextItem({
                                    cls: 'chapter-title-editor',
                                    text: '___'
                                }),
								'->',
								//'-',
								{
									text: '...',
									xtype: 'tbtext',
									ref: 'keywordsSyummary',
									hidden: true,
									//cls: 'icon-words-gray',
									cls: 'direction-arrow',
									style: 'color: #0000C0; background-repeat: no-repeat; padding-left: 20px;'
								}
                            ]
                        })
                    ]
                }),
				cm: new Ext.grid.ColumnModel({
					columns: columns
				}),
				bbar: new Bible.NavigationToolbar({
					buttonAlign: 'center',
					store: me.store,
					grid: me
				})
			});

			BibleGridPanel.superclass.initComponent.call(me);

            me.addEvents(
                /**
                 * @event refclick
                 * Fires on reference click.
                 * @param {Number} id ID of verse reference
                 */
                "refclick"
            );
			
			me.store.on({
                load : function(s){
                    //--console.debug('store.load', s.reader.arrayData);
                    var arrayData = s.reader.arrayData,
                        theme = arrayData ? arrayData.theme : '____';
                    me.titleEditor.setText(theme);
                }
            });
		},

		initEvents: function(){
			var me = this,
                view = me.getView(),
                store = me.store,
                booksCombo = me.booksCombo,
                arr = [],
                titleEditor = me.titleEditor,
				record = me.booksStore.getById(me.defaultBook);
            BibleGridPanel.superclass.initEvents.apply(me, arguments);

            me.keyMap.stopEvent = false;

			for(var i=1; i<=record.get('chapters'); i++){
				arr.push([i]);
			}
			me.chaptersStore.loadData(arr);

            // remove removeListener mousewheel to continue editing
            var el = me.getGridEl(),
                e = Ext.EventManager.getListeners(el, 'mousewheel');
            if(e && e[0]){
                Ext.EventManager.removeListener(el, 'mousewheel', e[0][0]);
            }

            me.on({
                scope: me,
                cellclick: function(grid, row, column, e){
                    if (column == 1){
                        var target = e.getTarget('span.ref');
                        if(target){
                            var record = store.getAt(row),
                                ref = record.get('ref'),
                                text = target.innerHTML,
                                id = ref.split('">'+text)[0].split('#');
                            id = id[id.length-1];
                            //--console.debug(id, ' - ', text);
                            me.fireEvent('refclick', id, text);
                        }
                    }
                },
                cellcontextmenu: function(thisGrid, rowIndex, cellIndex, e) {
                    e.stopEvent();
                    me.selModel.selectRow(rowIndex);
                    me.verseMenu.showAt(e.getXY());
                },
                afteredit: function(e){
                    Bible.updateDBObj('edit', e, CHAPTERS_URL, function(){
                        Bible.EventManager.fireEvent('versechange', me, e.record.get('id'), e.field, e.value);
                    });
                }
//                ,
//                mouseup: function(e){
//                    var s = window.getSelection();
//                    if(s.toString().length > 1){
//                        //--console.debug('window.getSelection:', s.toString());
//                        this.verseMenu.showAt(e.getXY());
//                    }
//                }
            });

            me.view.on({
				scope: me,
                beforerefresh: function(){
					//--console.debug('beforerefresh');
                    me.keywordsMatches = [];
                },
                refresh: me.onRefresh
            });

            me.getSelectionModel().on({
                scope: me,
                rowselect: function(sm, index, r){
                    me.verseButton.enable();
                    me.verseMenu.enable();
                    me.verseMenu.keyVerse.setChecked(r.get('keyverse'), true);
                },
                clearselections: function(){
                    me.verseButton.disable();
                }
            });

            me.commentEditor.on('show', function() {
                var h = me.getView().getCell(store.indexOf(me.getSelectionModel().getSelected()), 2).clientHeight;
                this.setSize(this.getWidth() + 3, h + 2);
            });

            var titleTextFieldEditor = new Ext.Editor(Ext.apply({
				alignment: 'l-l',
                autoSize: "width",
                listeners: {
                    complete: function(ed, value, oldValue){
                        me.doLayout(); // fix height if toolbar has changed size
                        if(Bible.isLogged()){
                            var lastParams = me.lastParams;
                            Ext.Ajax.request({
                                url: BOOKS_URL,
                                params: Ext.apply({
                                    action: 'edit',
                                    theme: value
                                }, lastParams),
                                success: function(){
                                    Bible.EventManager.fireEvent('themechange', me, lastParams.book, lastParams.chapter, value);
                                }
                            });
                        } else {
                            Bible.notifyNotLogged();
                        }
                    }
                },
                field: {
                    allowBlank: false,
                    xtype: 'textfield',
                    cls: 'bold theme-editor',
                    boxMinWidth: 150,
                    maxLength: 255,
                    selectOnFocus: true
                }
            }, {
                shadow: false,
                completeOnEnter: true,
                cancelOnEsc: true,
                updateEl: true,
                ignoreNoChange: true
            }));
            titleEditor.el.on('click', function(e, t){
                titleTextFieldEditor.startEdit(t);
            });

            if(me.autoLoadChapter){
                me.loadData({
                    book: me.defaultBook,
                    chapter: me.defaultChapter
                }, me.defaultVerse);
            }

			// =====

			booksCombo.on({
//				scope: me,
				select: function(combo, record, index){
					me.booksComboChange(record);
				},
				change: function(combo, newValue, oldValue){
                    //--console.debug('booksCombo.on.change:', newValue, '->', oldValue);
					var record = combo.findRecord(combo.valueField, newValue);
					if(record){
                        //--console.debug('record change', record.get('id'), record.get('name'));
                        me.booksComboChange(record);
                    } else {
                        //--console.debug('booksCombo change, no record selected. oldValue=', oldValue);
                        combo.setValue(oldValue);
                    }
				}
			});

			me.chaptersCombo.on({
//				scope: me,
				select: function(combo, record, index){
					me.loadData({
						book: booksCombo.getValue(),
						chapter: record.get('id')
					});
				},
				change: function(combo, newValue, oldValue){
					var record = combo.findRecord(combo.valueField, newValue);
					if(record){
                        me.loadData({
                            book: booksCombo.getValue(),
                            chapter: record.get('id')
                        });
                    } else {
                        ////--console.debug('chaptersCombo change, no record selected. oldValue=', oldValue);
                        combo.setValue(oldValue);
                    }
				}
			});

            me.mon(Bible.data.KeywordsStore, {
                scope: me,
                add:    me.keywordsStoreChanged,
                remove: me.keywordsStoreChanged,
                update: me.keywordsStoreChanged
            });

            me.mon(Bible.EventManager, {
//                scope: me,
                versechange: function(grid, id, property, value){
                    if(me != grid){
                        var record = store.getById(id);
                        if(record){
                            record.set(property, value);
                            record.commit();
                        }
                    }
                },
                themechange: function(grid, book, chapter, newTheme){
                    //--console.info('themechange', book, chapter, newTheme);
                    if(me != grid && me.isEqual({book: book, chapter: chapter})){
                        titleEditor.setText(newTheme);
                    }
                }
            });

            new Ext.ToolTip({
                target: me.titleEditor.el,
                html: i18n.clickToEdit,
                anchor: 'br-tr',
                renderTo: document.body
            });
            me.clickToEditTip = new Ext.ToolTip({
                target: me.getView().mainBody,
                delegate: 'td.x-grid3-td-comments',
                html: i18n.clickToEdit,
                anchor: 'br-tr',
				renderTo: document.body
            });

            me.commentImgTip = new Ext.ToolTip({
                target: view.mainBody,
                delegate: 'td.comment-knotes',
                trackMouse: true,
                anchor: 'br-tr',
                renderTo: document.body,
                listeners: {
                    beforeshow: function(tip) {
                        var rowIndex = view.findRowIndex(tip.triggerElement),
                            comment = store.getAt(rowIndex).get('comment');
                        comment = Bible.rendererComments(comment);
                        tip.body.dom.innerHTML = comment;
                    }
                }
            });
		},

		// private
		onRefresh: function(){
			var me = this,
				keys = {},
				words = [],
				moreMatches = true,
				summary = [],
				keywordsSyummary = me.titleToolbar.keywordsSyummary;
			//--console.debug('onrefresh');
			Ext.each(me.keywordsMatches, function(e){
				var id = e.term.id;
				if(!keys[id]){// create if doesn't exist
					keys[id] = 0;
				}
				keys[id]++;
			});
			////--console.debug('keys', keys);

			Ext.iterate(keys, function(id, total){
				var key,
					record = Bible.data.KeywordsStore.getById(id);
				if(record){
					key = record.get('keywords');
					key = key.split(',')[0];
					words.push({
						id: id,
						key: key,
						total: total
					});
				}
			});
			words.sort(function (a, b) {
				return b.total - a.total;
			});

			////--console.info('keywords summary words');
			////--console.dir(words);
			Ext.each(words, function(e){
				var space = '';
				if(moreMatches && e.total == 1){
					space = '<br>';
					moreMatches = false;
				}
				summary.push(space + e.key + '&nbsp;(' + e.total + ')');
			});
			keywordsSyummary.setVisible(summary[0] ? true : false);
			var text = (summary[0] || '') + (summary[1] ? (', ' + summary[1]) : '') + '...';
			text = text.replace('<br>', '');
			keywordsSyummary.setText(text);
			keywordsSyummary.el.dom.qtip = '<b>Sumar ' + i18n.keywords + ':</b><br/>' + summary.join('; ');
			
			if(me.store.isBeforeFilter !== true){
				me.focusLastVerse();
			}
		},
		
		// re focus last verse
		focusLastVerse: function(){
			var me = this,
				record = me.getSelectionModel().getSelected();
			if(record){
				me.selectVerse(record.get('vnumber'));
			}
		},
		
        keywordsStoreChanged: function(){
            if(this.store.showKeywords){
                //--console.debug('keywords store update');
                this.view.refresh();
            }
        },

		booksComboChange: function(record){
			//--console.debug('booksComboChange', record.data);
            var me = this,
                p = me.store.lastOptions.params,
				lastChapter = record.get('lastLoaded'),
				chapter = lastChapter ? lastChapter : 1,
				verse,
				params = me.booksCombo.bookExtraParams;
			if(params){
				chapter = params.chapter;
				verse = params.verse;
				//--console.info('advanced set chapter from book combo', params);
			}
			if(p && (p.book != record.get('id') || p.chapter != chapter)) {
                me.resetNumberOfVerses(record);

				me.chaptersCombo.setValue(chapter);

                me.loadData({
					book: record.get('id'),
					chapter: chapter
				}, verse);
			} else {
				if(verse){
					me.selectVerse(verse);
				}
			}
		},

        /**
         * @param {Ext.data.Record} record Record-book
         */
        resetNumberOfVerses: function(record, book){
            //--console.debug('resetNumberOfVerses');
            var me = this,
                i = 1,
                a = [],
                lastOptions = me.store.lastOptions;
            if(!record){
                record = me.booksStore.getById(book);
            } else {
                book = record.get('id');
            }
            if(!lastOptions || book != lastOptions.params.book){
                //--console.debug('book changed to:', book);
                for(; i<=record.get('chapters'); i++){
                    a.push([i]);
                }
                me.chaptersStore.loadData(a);
            }
        },

        /**
         *
         * @param {Object} params
         * @return {Boolean}
         */
        isEqual: function(params){
            // TODO use me.lastParams
            var lastOptions = this.store.lastOptions;
            return ((lastOptions) && Bible.deepEquals(params, lastOptions.params, ['action', 'titles', 'references']));
        },

		/**
		 * @param {Object} params
         * @param {Number} verse - verse to select
		 */
		loadData: function(params, verse){
			////--console.debug('loadData', Ext.encode(params));
//			Ext.applyIf(params, {
//				book: this.defaultBook,
//				chapter: this.defaultChapter
//			});
            var me = this,
                record,
                action;

			if(!me.isEqual(params)){

                if(verse){
                    me.selectVerseAfterLoad(verse);
                }
				record = me.booksStore.getById(params.book);
                me.lastParams = Bible.deepCloneObject(params);
				// fix params
				if(record && record.get('chapters') < params.chapter){
					params.chapter = record.get('chapters');
					me.setPage(params, verse);
					return;
				}
				me.store.load({
					params: params
				});

                if(me.hashBook){
                    action = params.book + separator + params.chapter;
                    if(me.defaultVerse){
                        action += separator + me.defaultVerse;
                        // TODO for the moment don't have verse in all actions (like click on verse)
                        delete me.defaultVerse;
                    }
                    Bible.setActions(me.hashBook, action);
                }

				// remember last viewed chapter for every Book
				if(record){
					record.set('lastLoaded', params.chapter);
				}
                me.fireEvent('pagechange', me, params);
				////--console.debug('lastOptions: ', Ext.encode(this.store.lastOptions));
			}
		},

        /**
         * @param {Object} params {book: 1, chapter: 2}
         * @param {Number} verse - verse to select
         */
        setPage: function(params, verse){
            //--console.debug('setPage', params, verse);
            var me = this;
            me.booksCombo.setValue(params.book);

            me.resetNumberOfVerses(null, params.book);

            me.chaptersCombo.setValue(params.chapter);
            me.loadData(params, verse);
        },

        getVerseDetails: function(id, text){
            //--console.debug('getVerseDetails', id, text);
            Ext.Ajax.request({
                url: VERSE_URL,
                method: 'GET',
                disableCaching: false,
                params: {
                    action: 'get_details',
                    id: id
                },
                scope: this,
                success: function(response){
                    var params = Ext.decode(response.responseText),
                        verse = params.verse;
                    delete params.verse;
                    //--console.debug('getVerseDetails', params);
                    if(!this.isEqual(params)){
                        this.setPage(params, verse);
                    } else {
                        this.selectVerse(verse);
                    }
                }
            });
        },

        /**
         *
         */
        copyText: function(){
            //--console.warn('TODO copyText');
            var verse,
                record = this.selModel.getSelected();
            if(record){
                verse = this.booksCombo.getRawValue() + ' ' + record.get('cnumber')+':'+ record.get('vnumber');
                verse += ' ' + record.get('text');
                //--console.debug('Copy:', verse);
                Bible.copyToClipboard(verse);
            }
        },

        toggleTitles : function(button, pressed){
            this.store.setBaseParam('titles', pressed);
            this.view.refresh();
        },

        toggleKeywords: function(button, show){
            this.store.showKeywords = show;
            //--console.time('toggleKeywords');
            this.view.refresh();
            //--console.timeEnd('toggleKeywords');
        },

        toggleBackgroundColors: function(button, pressed){
            this.store.showBackgroundColors = pressed;
            this.view.refresh();
        },

        toggleReferences : function(button, pressed){
            var me = this,
                store = me.store;
            store.setBaseParam('references', pressed);
            Ext.apply(store.lastOptions.params, {
                references: pressed
            });
            if(pressed){
                ////--console.debug('toggleReferences reload');
                store.reload();
            } else {
                ////--console.debug('toggleReferences refresh');
                me.view.refresh();
            }
        },

        /**
         * @param {Number} verse
         */
        selectVerseAfterLoad: function(verse){
            this.store.on('load', function(){
                //--console.debug('store load: selectRow & focusRow');
                this.selectVerse(verse);
            }, this, {single: true});
        },

        /**
         * @param {Number} verse
         */
        selectVerse: function(verse){
            //--console.info('selectVerse', verse);
            var me = this;
            if(!me.rendered){
                me.on({
                    single: true,
                    afterrender: function(){
                        //--console.debug('afterrender -> selectVerse', verse);
                        me.selectVerse.defer(200, me, [verse]);
                    }
                });
                return;
            }
            me.getSelectionModel().selectRow(verse-1);
            (function(){
                me.view.focusRow(verse-1);
            }).defer(10, me);
        },

        //private
        setSelectedRecordValue: function(name, value){
            var record = this.getSelectionModel().getSelected();
            if(record){
                var e = {
                    record: record,
                    field: name,
                    value: value
                };
                record.set(name, value);
                Bible.updateDBObj('edit', e, CHAPTERS_URL, function(){
                    Bible.EventManager.fireEvent('versechange', this, record.get('id'), name, value);
                }, this);
            }
        },

        //private
        setBackgroundColor: function(color){
            this.setSelectedRecordValue('bgcolor', color);
        },

        //private
        setKeyVerse: function(checked){
            this.setSelectedRecordValue('keyverse', checked ? '1' : '');
        },

        // private
        getTopToolbarItems: function(){
            var me = this;
            me.booksCombo = new Bible.form.BibleBooksComboBox({
				width: 135,
				listWidth: 150,
                value: me.defaultBook
            });
            me.booksStore = me.booksCombo.store;
            return [
                {
					xtype: 'spacer',
					cls: 'toolbar-icon'
				},
                me.booksCombo,
                me.chaptersCombo = new Ext.form.ComboBox({
                    width: 45,
                    listWidth: 45,
                    displayField:'id',
                    valueField: 'id',
                    value: this.defaultChapter,
                    mode: 'local',
                    allowBlank: false,
                    selectOnFocus: true,
                    lastQuery: '',
                    lazyInit: false,
                    lazyRender: false,
                    forceSelection: true,
                    typeAhead: true,
                    triggerAction: 'all',
                    editable: true,
                    listClass: 'x-combo-list-small',
                    store: me.chaptersStore
                })
                //'->',
                //me.searchField,
				//me.checkFilter
            ];
        },

        getSecondTopToolbarItems: function(){
            var me = this,
                store = me.store,
                baseStateId = 'BibleGridPanel' + (me.hashBook || '') + '-';
            me.verseMenu = new Ext.menu.Menu({
                items: [
                    {
                        text: i18n.backgroundColor,
                        iconCls: 'color-swatch',
						hideOnClick: false,
                        menu: [
                            new Ext.ColorPalette({
                                style: "height: 72px",
                                colors : [
                                    //'000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333',
                                    '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080',
                                    'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696',
                                    'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0',
                                    'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF'
                                ],
                                scope: me,
                                handler: function(palette, color) {
                                    //--console.debug('color:', color);
                                    me.setBackgroundColor(color);
                                    me.verseMenu.hide();
                                }
                            }),
                            '-',
                            {
                                text: 'Transparent', // TODO i18n
                                iconCls: 'icon-transparent',
                                scope: me,
                                handler: function(){
                                    me.setBackgroundColor('');
                                }
                            }
                        ]
                    }, {
                        text: 'Verset Cheie', // TODO i18n
                        ref: 'keyVerse',
                        checked: true,
                        scope: me,
                        checkHandler: function(item, checked){
                            //--console.debug('keyVerse', checked);
                            me.setKeyVerse(checked);
                        }
                    }
                ]
            });

            if(Ext.isIE){
                me.verseMenu.add('-', {
                    text: i18n.copyText,
                    icon: 'images/copy.png',
                    scope: me,
                    handler: me.copyText
                });
            }

            return [
                '-',
                {
                    tooltip: i18n.titles,
                    iconCls: 'chapter-titles',
                    enableToggle: true,
                    pressed: Bible.defaults.titles,
                    stateful: true,
                    stateId: baseStateId + 'titles',
                    stateEvents: ['toggle'],
                    getState : function(){
                        return Ext.apply(Ext.Button.prototype.getState.call(this) || {}, {pressed: this.pressed});
                    },
                    listeners: {
                        scope: me,
                        staterestore: function(button, state){
                            //--console.debug(button.stateId, 'pressed:', button.pressed);
                            store.setBaseParam('titles', button.pressed);
                        }
                    },
                    scope: me,
                    toggleHandler: me.toggleTitles
                },
                me.referencesButton = new Ext.Button({
                    tooltip: i18n.references + ' (Shift + R)',
                    iconCls: 'chapter-references',
                    enableToggle: true,
                    pressed: Bible.defaults.references,
                    stateful: true,
                    stateId: baseStateId + 'references',
                    stateEvents: ['toggle'],
                    getState : function(){
                        return Ext.apply(Ext.Button.prototype.getState.call(this) || {}, {pressed: this.pressed});
                    },
                    listeners: {
                        scope: me,
                        staterestore: function(button, state){
                            //--console.debug(button.stateId, 'pressed:', button.pressed);
                            store.setBaseParam('references', button.pressed);
                        }
                    },
                    scope: me,
                    toggleHandler: me.toggleReferences
                }),
                '-',
				/*
                me.userTitleButton = new Ext.Button({
                    tooltip: i18n.chapterTheme,
                    pressed: true,
                    enableToggle: true,
                    iconCls: 'title-chapter-edit',
                    toggleHandler: function(button, pressed){
                        me.titleToolbar.setVisible(pressed);
                        me.doLayout();
                    }
                }),
				*/
                me.commentsButton = new Ext.Button({
                    tooltip: i18n.showHideComments + ' (Shift + C)',
                    enableToggle: true,
                    iconCls: 'icon-notes',
                    stateful: true,
                    stateId: baseStateId + 'comments',
                    stateEvents: ['toggle'],
                    getState : function(){
                        return Ext.apply(Ext.Button.prototype.getState.call(this) || {}, {pressed: this.pressed});
                    },
                    scope: me,
                    toggleHandler: function(button, pressed){
                        me.getColumnModel().setHidden(2, !pressed);
                        me.getColumnModel().setHidden(3, pressed);
						me.focusLastVerse();
                    }
                }),
                //'-',
                me.keywordsButton = new Ext.Button({
                    tooltip: i18n.keywords + ' (Shift + K)',
                    iconCls: 'icon-words',
                    enableToggle: true,
                    pressed: false,
                    stateful: true,
                    stateId: baseStateId + 'keywords',
                    stateEvents: ['toggle'],
                    getState : function(){
                        return Ext.apply(Ext.Button.prototype.getState.call(this) || {}, {pressed: this.pressed});
                    },
                    listeners: {
                        scope: me,
                        staterestore: function(button, state){
                            //--console.debug(button.stateId, 'pressed:', button.pressed);
                            store.showKeywords = button.pressed;
                        }
                    },
                    scope: me,
                    toggleHandler: me.toggleKeywords
                }),
                {
                    tooltip: 'Activează/Dezactivează ' + i18n.backgroundColor,
                    iconCls: 'color-swatch',
                    enableToggle: true,
                    pressed: true,
                    stateful: true,
                    stateId: baseStateId + 'bgcolors',
                    stateEvents: ['toggle'],
                    getState : function(){
                        return Ext.apply(Ext.Button.prototype.getState.call(this) || {}, {pressed: this.pressed});
                    },
                    listeners: {
                        scope: me,
                        staterestore: function(button, state){
                            //--console.debug(button.stateId, 'pressed:', button.pressed);
                            store.showBackgroundColors = button.pressed;
                        }
                    },
                    scope: me,
                    toggleHandler: me.toggleBackgroundColors
                },
                //'-',
                me.verseButton = new Ext.Button({
                    tooltip: i18n.verse,
                    disabled: true,
                    iconCls: 'blist',
                    menu: me.verseMenu
                }),
                //,
//                {
//                    text: 'Capitol',
//                    iconCls: 'icon-book',
//                    menu: new Ext.menu.Menu({
//                        items: [
//                            {
//                                text: 'Sumar',
//                                iconCls: 'icon-book-edit'
//                            }
//                        ]
//                    })
//                }
				'->',
                me.searchField,
				me.checkFilter
            ];
        }
	});
    Bible.BibleGridPanel = BibleGridPanel;

    Ext.reg('biblegridpanel', BibleGridPanel);
})();
(function(){
    var KeywordsStore,
        KEYWORDS_URL = 'servlets/keywords.php';

    if(!Bible.loggedUser){
        // DEMO keywords
        Bible.records.keywords = {
            success:true,
            data:[["2","Dumnezeu, Dumnezeule, Dumnezeul, Dumnezeului, Cel Sf\u00e2nt, Celui Sf\u00e2nt, Cel Atotputernic, Celui Atotputernic, Numele Lui, Numelui Lui, Meu, Mei, Mine, Mele, Mea, T\u0103u, T\u0103i, Tale, Ta, Sa, S\u0103u, Sale, Tine, Domnul, Doamne, Domnului, Sf\u00e2ntul lui Israel, Sf\u00e2ntului lui Israel, Cel Prea\u00eenalt, Celui Prea\u00eenalt, Ziditorului","background-color: #FFFF00; border-top: 1px solid #00FF00; border-right: 1px solid #00FF00; border-bottom: 2px solid #00FF00; border-left: 2px solid #00FF00;","","1"],["3","Duhul Sf\u00e2nt, Duh Sf\u00e2nt, Duhul S\u0103u, Sf\u00e2ntului Duh, Duhului Sf\u00e2nt, Duhului, Duhul","background-color: #FFFF00; border-top: 1px solid #3366FF; border-right: 1px solid #3366FF; border-bottom: 2px solid #3366FF; border-left: 2px solid #3366FF;","","1"],["4","Domnul Isus, Isus Hristos, Hristos Isus, Domnul Isus Hristos, Domnului Isus Hristos, Domnului Isus, Doamne Isuse, Isus, Hristos, Mesia, Fiu, Apostolul \u015fi Marele Preot, Celui Neprih\u0103nit, Isuse, Hristosul, \u00cenv\u0103\u0163\u0103torule, M\u00e2ntuitor, M\u00e2ntuitorul, Sine","background-color: #FFFF00; border-top: 1px solid #FF0000; border-right: 1px solid #FF0000; border-bottom: 2px solid #FF0000; border-left: 2px solid #FF0000;","","1"],["5","Satana, Satanei, dracului, dracilor, diavolul","background-color: #C0C0C0; border: 1px dotted #FF0000;","","1"],["7","dragoste, Dragostea, dragostea, dragostei, iube\u015fte, iubit, iubit\u0103, iubesc, iubeam, iubi, iube\u015fti, iubi\u0163i-v\u0103, iubeasc\u0103, iube\u015fte-o","background-color: #FF0000; border: 1px solid #FFFFFF;","","1"],["19","crede, cred, credin\u0163\u0103, credin\u0163a, crezi, cread\u0103, crezut, crede\u0163i, credincios, Credincio\u015fia, credincio\u015fia, credincio\u015fie, credincio\u015filor, credincio\u015fi, credincio\u015fii, Credincios, credin\u0163ei, crezuser\u0103, credeau, credincioas\u0103, credincioase, Crezi","background-color: #00FF00; border: 1px solid #FFFF99;","","1"],["20","Ferice, ferice, fericit, fericire, fericirea, ferici\u0163i, bucur\u0103-te, bucura, bucurie, bucuria, bucur, bucuri, veselie, veselia, veseliei, vesel\u0103, \u00eenveseli, bucurii, bucuriile, bucur\u0103, bucura\u0163i-v\u0103, Bucura\u0163i-v\u0103, bucuriei, bucure, \u00eenvesele\u015fte, bucurat, bucur\u0103m, \u00eenveseli\u0163i-v\u0103","background-color: #FFFFFF; border: 2px solid #00FF00;","","1"],["22","Cuv\u00e2ntul, Legea, Lege, Legii, Scriptura, Scriptur\u0103, Scripturi, Scripturile, Sfintele Scripturi, Evanghelia, Evanghelie, Evangheliei, Cuv\u00e2ntului","border-top: 3px double #FFFF00; border-right: 3px double #FFFF00; border-bottom: 3px ridge #FFFF00; border-left: 3px groove #FFFF00;","","1"],["23","leg\u0103m\u00e2nt, Leg\u0103m\u00e2nt, leg\u0103m\u00e2ntul, leg\u0103m\u00e2ntului","border-top: 1px solid #0000FF; border-right: 3px double #0000FF; border-bottom: 1px solid #0000FF; border-left: 3px double #0000FF;","","1"],["24","minune, minuni, minunile, semn, semne, semnele, Minunea","border: 1px solid #800000;","","1"],["27","Lumina, Lumin\u0103, lumineaz\u0103, lumina","background-color: #FF0000; border: 1px solid #FFFF00;","","1"],["29","p\u0103cat, p\u0103catul, p\u0103catului, p\u0103cate, p\u0103catele, p\u0103catelor, p\u0103c\u0103tui, p\u0103c\u0103tuie\u015fte, p\u0103c\u0103tuiasc\u0103, p\u0103c\u0103tuit, p\u0103c\u0103tui\u0163i, p\u0103c\u0103tuiesc, p\u0103c\u0103to\u015fi, p\u0103c\u0103to\u015fii, f\u0103r\u0103delege, f\u0103r\u0103delegea, f\u0103r\u0103delegile, f\u0103r\u0103delegilor, f\u0103r\u0103delegi, f\u0103r\u0103delegii, F\u0103r\u0103delegea, P\u0103c\u0103to\u015fii, p\u0103c\u0103to\u015filor, nelegiuit, nelegiuiri, nelegiuirea, nelegiuite, nelegiuirilor, nelegiuirii, nelegiuirile, nelegiuire, Nelegiuirea, nedreptate, nedrepte, p\u0103c\u0103tosului, p\u0103c\u0103tos, p\u0103c\u0103tuie\u015fti, p\u0103c\u0103tuirea, nelegiui\u0163i, nelegiuit\u0103","background-color: #E0E0E0; border: 1px solid #969696;","","1"],["37","dumnezeu, dumnezeul, dumnezeului, dumnezei, dumnezeilor, dumnezeii, idoli, idolii, idolilor, idole\u015fti, Moloh, Baal, Baalilor, Dumnezeii, Idolul, chipuri turnate, Astarteele, Idolii, zeului Remfan, idolului, zeii, zei\u0163e, zei\u0163ei","background-color: #C0C0C0; border-top: 1px solid #333333; border-right: 1px solid #333333; border-bottom: 2px solid #333333; border-left: 2px solid #333333;","","1"],["43","binecuv\u00e2nta, binecuv\u00e2ntat, binecuv\u00e2ntat\u0103, binecuv\u00e2ntate, binecuv\u00e2ntare, binecuv\u00e2ntarea, binecuv\u00e2nt\u0103rile, binecuv\u00e2nteze, binecuv\u00e2nt\u0103ri, Binecuv\u00e2ntat, Binecuv\u00e2ntat\u0103, binecuv\u00e2ntezi, binecuv\u00e2nteaz\u0103, binecuv\u00e2nta\u0163i, Binecuv\u00e2nta\u0163i, binecuv\u00e2ntez, Binecuv\u00e2nteaz\u0103, binecuv\u00e2ntau, binecuv\u00e2nt\u0103m, Binecuv\u00e2nt\u0103rile, Binecuv\u00e2ntarea","background-color: #FFFFFF; border: 2px solid #FFFF00;","","1"],["46","murit, mort, mor, Moartea, moartea, moar\u0103, muri, mor\u0163i, mor\u0163ii, mor\u0163ilor,  moare, moarte, Mor\u0163ii, Mor\u0163i, omor\u00e2t, omoare, omori, omoar\u0103, omorau, ucizi, ucis, uci\u015fi, uciderile, ucid\u0103, omoruri, ucide, uciderea, sp\u00e2nzurat, morm\u00e2nt, morm\u00e2ntul, mortului, mortul","border: 1px solid #808080;","","1"],["47","timpul, ast\u0103zi, azi, zi, ziua, zilele, Ziua, seara, sear\u0103, noapte, noaptea, nop\u0163ii, diminea\u0163a, dimine\u0163ile, dis-de-diminea\u0163\u0103, amiaz\u0103, vreme, vremea, vremurile, veac, veci, vecie, atunci, Atunci, zile, an, anul, ani, anii, a lunii, \u00een luna, \u00cen luna, din luna, luna a \u015faptea, lunii a \u015faptea, s\u0103pt\u0103m\u00e2ni, ceasul, Acum, acum, deodat\u0103, \u00cendat\u0103","border-bottom: 3px double #0000FF;","","1"],["48","adev\u0103rat, Adev\u0103rat, adev\u0103rului, adev\u0103rate, adev\u0103rul, adev\u0103rat\u0103, adev\u0103r, Adev\u0103rata, drept, dreptate","border-bottom: 2px solid #00FF00;","","1"],["49","jertfa, jertf\u0103, jertfe, jertfei, jertfele, jertfelor, jertfe\u015fti, jertfesc, arderea de tot, arderi de tot, Arderea de tot, ardere de tot, jertfit, jertfite","border-bottom: 2px solid #FF0000;","","1"],["50","fapte, faptele","border-bottom: 2px dashed #00FF00;","","1"],["51","\u00centoarce\u0163i-v\u0103, \u00eentoarce\u0163i-v\u0103, abate\u0163i-v\u0103, Asculta\u0163i, asculta\u0163i, C\u0103uta\u0163i-M\u0103","border-bottom: 1px solid #0000FF;","","1"],["52","\u0163ar\u0103, \u0163ara, \u0163\u0103rii, \u0163\u0103rile, \u0162ara, Ierusalim, Ierusalimul, Betleeme, Ierusalimului, Israel, Israele, Egipt, Egiptul, Egiptului, Tars, Eden, Edenului, Hetlon, Babilon, Galaad, Babilonului, Edom, Edomului, Tirul, Tirului, Tirule, Basan, Chitim, Sidon, Sidonule, Liban, Persia, Etiopia, Damascul, Damascului, Ninive, Ninivei, Sodoma, Gomora, Asiria, Etiopiei, Gaza, Samaria, Samariei, Iudea, p\u0103m\u00e2ntului, Nazaret, sate, Corint, Galilea, Galileii, Nazaret, Nazaretul, Capernaum, Asia, Antiohia, Canaanului","border-top: 1px dotted #008000; border-right: 1px dotted #008000; border-bottom: 3px double #008000; border-left: 1px dotted #008000;","","1"],["53","Sf\u00e2ntul, sf\u00e2nt, sfinte, sf\u00e2nt\u0103, sf\u00e2ntul, sfin\u0163i\u0163i, Sfin\u0163ii, evlavios, evlavio\u015fi, sfin\u0163enia, sfin\u0163ilor","background-color: #FFFF99; border: 1px dotted #FFFF00;","","1"],["54","curvit, curv\u0103, curvie, curviei, curvise, curviile, curve\u015fte, curvar, preacurv\u0103, prea curve, curvesc, curve, curvii, curvei, curvarii, preacurvarii, curvelor, preacurve\u015fti, preacurvie, preacurvia, curvim, curvele, preacurve","background-color: #F0F0F0; border: 1px solid #CCFFFF;","","1"],["56","min\u0163i, min\u0163it, mint, minciuni, minciunile, mincinoase, minciuna, minciun\u0103, mincino\u015fi, Minciun\u0103, \u00een\u015fel\u0103toria, \u00een\u015feal\u0103, \u00een\u015fel\u0103tor, \u00een\u015fel\u0103toare, \u00een\u015fel\u0103ciune, \u00een\u015fel\u0103ciunea, \u00cen\u015fel\u0103toria, vicle\u015fug, vicle\u015fugul, r\u0103pitorul, jefui, ho\u0163, ho\u0163i, jefuite, jefuiesc, jefuie\u015fte, Jefui\u0163i, ho\u0163ul, r\u0103utate, r\u0103utatea, batjocoritorii, m\u00e2ndria, m\u00e2ndrie, r\u0103zvr\u0103tesc, r\u0103ut\u0103\u0163ii, r\u0103u, r\u0103ul, r\u0103i, rele, silnicie, silnicia, r\u0103pire, de\u015fert\u0103ciunea, mincinos, mincinosul, fura, fure, fur, tic\u0103lo\u015fia, netrebnic, netrebnici, mit\u0103, neadev\u0103ruri, mincino\u015fii, r\u0103ut\u0103cioase, viclenie, minciunii, neadev\u0103rul, mincinoas\u0103","background-color: #F0F0F0; border: 1px solid #C0C0C0;","","1"],["57","poc\u0103ie\u015fte-te, Poc\u0103ie\u015fte-te, Poc\u0103i\u0163i-v\u0103, poc\u0103in\u0163a, poc\u0103in\u0163\u0103, poc\u0103in\u0163ei, poc\u0103it, poc\u0103i\u0163i, poc\u0103iasc\u0103","background-color: #00FF00; border: 1px solid #008000;","","1"],["59","rug\u0103ciunea, rug\u0103ciune, rog, rug\u0103ciunii, rug\u00e2ndu-se, rugat, rug\u0103ciuni, Ruga\u0163i-v\u0103, Rug\u0103ciunile, roage, rugam, rug\u0103m, rugau, roag\u0103-te, ruga, roag\u0103, rug\u0103ciunile, rug\u0103ciunilor","background-color: #00CCFF; border: 1px dashed #0000FF;","","1"],["60","bun\u0103tate, bun\u0103tatea","border-bottom: 2px solid #00FF00;","","1"],["69","dat, d\u0103ruit, daruri, d\u0103, Un dar","border-top: 4px double #0000FF; border-right: 3px double #0000FF; border-bottom: 1px inset #0000FF; border-left: 1px ridge #0000FF;","","1"],["72","botezat, boteza\u0163i, botezului, botezul, botezat\u0103, boteaz\u0103, boteza, botezase, botez","background-color: #00FFFF; border: 1px dashed #0000FF;","","1"],["76","David","border-bottom: 1px solid #800000;","","1"],["79","aur, aurul, aurului, argint, argintul, argintului, diamantul, m\u0103rg\u0103ritarele, safir, onixul","background-color: #FFDF00; border: 1px solid #FFFF99;","","1"],["80","\u00cen\u0163elepciunea, \u00een\u0163elepciune, \u00een\u0163elepciunea,\npricepere, priceperii, priceperea, pricepe\u0163i, \u00een\u0163elept, \u00een\u0163elep\u0163i, \u00een\u0163elepciunii, \u00een\u0163eleapt\u0103, \u00een\u0163elepte, \u00een\u0163elep\u0163ilor, \u00een\u0163eleptul, \u00cen\u0163eleptul, \u00een\u0163elep\u0163ii, \u00cen\u0163elep\u0163ii, \u00een\u0163eleptului","border-top: 1px dotted #0000FF; border-bottom: 1px dotted #0000FF;","","1"],["81","neprih\u0103nire, neprih\u0103niri, neprih\u0103nirea, Neprih\u0103nirea, neprih\u0103nit, nevinovat, nevinov\u0103\u0163ia, neprih\u0103nit\u0103, neprih\u0103ni\u0163i, neprih\u0103nirii, f\u0103r\u0103 prihan\u0103, neprih\u0103nite","background-color: #CCFFCC; border: 1px solid #FFFF00;","","1"],["82","gre\u015felile","background-color: #F0F0F0;","","1"],["115","via\u0163a ve\u015fnic\u0103","background-color: #CCFFCC; border-top: 1px solid #008000; border-bottom: 1px solid #008000;","","1"],["116","Templul, Templu, Templului","background-color: #FFCC99;","","1"],["132","Inima, inima, inim\u0103, inimi, inimii, inimile","border: 1px dotted #FF0000;","","1"],["133","nebun, nebunul, nebuniei, nebunilor, nebunului, Nebunul, nebunie, nebuni, nebunii, nebunia, nebun\u0103, Nebunia","background-color: #F0F0F0; border: 1px dotted #808080;","","1"],["134","m\u00e2ntuit, m\u00e2ntuire, m\u00e2ntui\u0163i, m\u00e2ntuiri, m\u00e2ntuirea, m\u00e2ntuirii","background-color: #CCFFCC; border-top: 1px dashed #008000; border-bottom: 1px solid #008000;","","1"],["135","se crede","background-color: #FF99CC; border-top: 2px dashed #00FF00; border-bottom: 2px dashed #FF0000;","","1"],["136","Har, har, Harul, harul, harului","background-color: #FFFF99; border-top: 1px solid #FFEF00; border-right: 1px solid #FFEF00; border-bottom: 1px solid #FFFF00; border-left: 1px solid #FFFF00;","","1"],["137","\u00cenger, \u00eenger, \u00eengerul, \u00cengerul, \u00eengerului","border-top: 4px double #FFFF00;","","1"],["138","\u00eempotriva, \u00eempotrivi, \u00eempotriv\u0103","background-color: #FFFFFF; border-right: 3px solid #FF0000; border-bottom: 1px dashed #FF0000;","","1"],["139","L\u0103uda\u0163i, l\u0103ud\u0103m, Laud\u0103, laud\u0103","border: 1px dotted #FF0000;","","1"],["140","Biserica, Biseric\u0103, Bisericile, Bisericii","background-color: #FF9900; border: 2px dotted #FFFFFF;","","1"],["141","tem\u0103tor, temerile, fric\u0103, tem, teme, teme\u0163i-v\u0103","border-top: 1px dashed #800000; border-right: 1px dotted #800000; border-bottom: 1px dashed #800000; border-left: 1px dotted #800000;","","1"],["142","propov\u0103duit, propov\u0103duirii","border-bottom: 1px dashed #00FF00;","","1"]]
        };
    }

    /**
     * @class Bible.data.KeywordsStore
     * @extends Ext.data.ArrayStore
     * @singleton
     */
    KeywordsStore = new Ext.data.ArrayStore({
        idIndex: 0,
        root: 'data',
        fields: [
            {name: 'id', type: 'int'},
            {name: 'keywords', type: 'string'},
            {name: 'style', type: 'string'},
            {name: 'cls', type: 'string'}
        ],
        data: Bible.records.keywords,
        keywordsReplace: [],
        
		divideKeywords: function(){
			this.keywordsReplace = Ext.util.Terminology.createTerms(this);
		}
    });
    Bible.data.KeywordsStore = KeywordsStore;

    KeywordsStore.on({
        scope: KeywordsStore,
        add:    KeywordsStore.divideKeywords,
        remove: KeywordsStore.divideKeywords,
        update: KeywordsStore.divideKeywords
    });

    KeywordsStore.divideKeywords();




    var borderTypes = [
        ['dotted',  'dotted'],
        ['dashed',  'dashed'],
        ['solid',   'solid'],
        ['double',  'double'],
        ['groove',  'groove'],
        ['ridge',   'ridge'],
        ['inset',   'inset'],
        ['outset',  'outset']
    ];

    /**
	 * @class Bible.grid.KeywordsEditorGridPanel
	 * @extends Ext.grid.GridPanel
	 */
	Bible.grid.KeywordsEditorGridPanel = Ext.extend(Ext.grid.GridPanel, {
		cls: 'bible-grid keywords-grid',
		//hideHeaders: true,
//		stripeRows: true,
		columnLines: true,
        //autoExpandColumn: 'text',
        trackMouseOver: false,

//        clicksToEdit: 1,

		initComponent: function(){
            var me = this,
                columns;
			// create the data store
			me.store = Bible.data.KeywordsStore;

            me.checkFilter = new Ext.Button({
                iconCls: 'icon-filter',
				tooltip: i18n.filter,
                pressed: true,
				enableToggle: true
			});

			// TODO must create termshighlight class only not search
			me.searchField = new Bible.form.SearchFieldLocal({
                emptyText: 'Caută...', // TODO i18n
                trigger2Qtip: 'Caută & Evidenţiază cuvintele cheie', // TODO i18n
				store: me.store,
				filterByFields: ['keywords'],
                checkFilter: me.checkFilter,
				split: true,
                width: 145
                //width: 185
			});
			me.store.searchField = me.searchField;

//            this.keywordsEditor = new Ext.form.TextArea({
//                style: 'padding: 1px 2px',
//                boxMinHeight: 45,
//                allowBlank: false,
//                minLength: 3
//            });

            columns = [
                new Ext.grid.RowNumberer({
                    width: 27
                }),
                {
                    width: 100,
                    dataIndex: 'keywords',
                    header: i18n.keywords,
                    renderer: Bible.rendererHighlight
//                    editor: new Ext.form.TextField({
//                    editor: this.keywordsEditor
                },
                {
                    dataIndex: 'keywords',
                    header: 'Vizualizare', // TODO i18n
                    id: 'text',
                    width: 50,
                    renderer: function(val, metaData, r, rowIndex, colIndex, store){
                        val = val.split(',')[0];
                        return Bible.util.Format.keywordText(val, r.get('style'), r.get('cls'));
                    }
                }
            ];

			Ext.apply(me, {
				viewConfig: {
                    autoFill: true,
					forceFit: true
//					scrollOffset: 1
				},
				sm: new Ext.grid.RowSelectionModel({
					singleSelect:true
				}),
				tbar: new Ext.Toolbar({
					items: [
                        me.newButton = new Ext.Button({
                            text: i18n.add,
                            iconCls: 'icon-add'
                        }),
                        me.removeButton = new Ext.Button({
                            text: i18n.remove,
                            iconCls: 'icon-delete',
                            disabled: true,
                            scope: me,
                            handler: me.doRemoveKeyword
                        }),
                        '->',
                        me.searchField,
                        me.checkFilter
                    ]
				}),
				cm: new Ext.grid.ColumnModel({
					columns: columns
				})
			});

			Bible.grid.KeywordsEditorGridPanel.superclass.initComponent.call(me);
		},

//		initEvents: function(){
//			Bible.grid.KeywordsEditorGridPanel.superclass.initEvents.apply(this, arguments);
//		},

        doRemoveKeyword: function(){
            //--console.debug('doRemoveKeyword');
            var msg,
                record = this.getSelectionModel().getSelected();
            if(record){
                msg = 'Doriţi să ştergeţi cuvintele: '+ record.get('keywords') + '?'; // TODO i18n
                Ext.Msg.confirm(i18n.remove, msg, function(btn){
                    if(btn == 'yes'){
                        if(Bible.isLogged()){
                            Ext.Ajax.request({
                                url: KEYWORDS_URL + '?action=remove',
                                params: {
                                    id: record.get('id')
                                },
                                scope: this,
                                success: function(response){
                                    if(response.responseSuccess){
                                        this.store.remove(record);
                                    }
                                }
                            });
                        } else {
                            this.store.remove(record);
                            Bible.notifyNotLogged();
                        }
                    }
                }, this);
            }
        }
	});

    Ext.reg('keywordseditorgridpanel', Bible.grid.KeywordsEditorGridPanel);


    /**
	 * @class Bible.KeywordsPanel
	 * @extends Ext.Container
	 */
	Bible.KeywordsPanel = Ext.extend(Ext.Container, {
        layout: 'border',
        border: false,
        bodyBorder: false,

        /**
         * used for local save id (demo)
         */
        tmpSaveNumber: 1000,

        initComponent: function(){
            var me = this;

            me.grid = new Bible.grid.KeywordsEditorGridPanel({
                border: false,
                style: 'border-right-width: 1px',
                region: 'center'
            });

            me.form = new Ext.form.FormPanel({
                border: false,
                autoScroll: true,
                bodyStyle: {
                    background: 'transparent',
                    // TODO verify why...
                    //padding: Ext.isIE ? '0 0 5px 15px;' : '10px 15px;'
                    padding: '10px'
                },
                width: 320,
                minSize: 320,
                maxSize: 320,
                region: 'east',
                labelAlign: 'right',
                labelWidth: 112,
                //split: true,
                items: [
                    {
                        xtype: 'hidden',
                        name: 'id'
                    },
                    {
                        xtype: 'fieldset',
                        title: '<div style="width: 250px" ext:qtip="'+ 'Cuvintele cheie (unul sau mai multe), separate prin virgulă' +'">&nbsp;Cuvintele separate prin virgulă<div>',
                        autoHeight: true,
                        hideLabels: true,
                        border: false,
                        style: 'padding: 5px 0 0 0',
                        items: [
                            me.keywordsEditor = new Ext.form.TextArea({
                                name: 'keywords',
                                anchor: '100%',
                                height: 60,
                                allowBlank: false,
                                enableKeyEvents: true,
                                minLength: 2
                            }),
                            new Ext.BoxComponent({
                                style: 'text-align: right;',
                                html: "<span ext:qtip=\"De exemplu 'lumina' nu va fi evidențiat în textul: 'Eu sunt Lumina lumii'\">* Se ține cont de litere mici/mari.</span>"
                            })
                        ]
                    },
                    me.backgroundColor = new Ext.form.ColorField({
                        fieldLabel: i18n.backgroundColor,
                        name: 'background-color',
                        showHexValue: true,
                        enableKeyEvents: true,
                        //anchor: '100%',
                        width: 75,
                        value: ''
                    }),
                    // TODO find better solution
//                    this.backgroundImage = new Ext.form.TextField({
//                        fieldLabel: 'Imagine de fondal',
//                        //name: 'background-image',
//                        name: 'cls',
//                        anchor: '100%',
//                        //width: 163,
//                        enableKeyEvents: true,
//                        value: ''
//                    }),
                    {
                        xtype: 'fieldset',
                        title: 'Chenare', // TODO i18n
                        autoHeight: true,
                        labelWidth: 65,
                        defaultType: 'compositefield',
                        defaults: {
                            combineErrors: false
                        },
                        items: [
                            {
                                fieldLabel: 'Sus',
                                items: me.getBorderItemsEditor('top')
                            }, {
                                fieldLabel: 'Dreapta',
                                items: me.getBorderItemsEditor('right')
                            }, {
                                fieldLabel: 'Jos',
                                items: me.getBorderItemsEditor('bottom')
                            }, {
                                fieldLabel: 'Stânga',
                                items: me.getBorderItemsEditor('left')
                            }
                        ]
                    },
					/*
					{
						xtype: 'fieldset',
						title: 'Chenare rotunjite',
						autoHeight: true,
                        labelWidth: 65,
                        defaultType: 'compositefield',
                        defaults: {
                            combineErrors: false
                        },
						items: [
							{
								fieldLabel: 'Sus Stanga',
								items: [
									me.getBorderRadiusEditor('top-left'),
									me.getBorderRadiusEditor('top-right')
								]
							},
							{
								fieldLabel: 'Jos Stanga',
								items: [
									me.getBorderRadiusEditor('bottom-left'),
									me.getBorderRadiusEditor('bottom-right')
								]
							}
						]
					},
					*/
                    me.previewKeyword = new Ext.BoxComponent({
                        cls: 'bible-grid',
                        height: 50,
                        data: {
                            text: 'text'
                        },
                        tpl:  new Ext.Template([
                            '<div class="x-grid3-td-text" style="background-color: white; padding: 5px;">',
                                '<b>Previzualizare</b>: <span class="x-grid3-cell-inner">{text}</span>',
                            '</div>'
                        ])
                    })
                ],
                buttons: [
//                    me.saveAndCloseButton = new Ext.Button({
//                        text: i18n.saveAndClose,
//                        iconCls: 'save',
//                        scope: me,
//                        handler: me.onSave
//                    }),
					me.saveButton = new Ext.Button({
                        text: i18n.save,
                        iconCls: 'save',
                        scope: me,
                        handler: me.onSave
                    }),
                    me.cancelButton = new Ext.Button({
                        text: i18n.cancel,
                        scope: me,
                        handler: function() {
                            //--console.debug('cancel');
                            this.onRowSelect();
                        }
                    })
                ]
            });

            Ext.apply(me, {
                items: [
                    me.grid,
                    me.form
                ]
            });

            me.plugins = [new Bible.CrudPlugin({
                grid: me.grid,
                form: me.form,
                newButton: me.grid.newButton,
                deleteButton: me.grid.deleteButton,
                cancelButton: me.cancelButton,
                saveButton: me.saveButton
            })];

            Bible.KeywordsPanel.superclass.initComponent.call(me);
        },

        afterRender : function(){
            Bible.KeywordsPanel.superclass.afterRender.call(this);
            this.initEvents();
        },

        initEvents: function() {
            var me = this;
            //Bible.KeywordsPanel.superclass.initEvents.apply(this, arguments);

            me.grid.getSelectionModel().on({
                scope: me,
                rowselect: function(sm, row, rec) {
                    me.grid.removeButton.setDisabled(false);
                    me.onRowSelect(rec);
                },
                clearselections: function(sm, row, rec){
                    me.grid.removeButton.setDisabled(true);
                    me.form.getForm().reset();
                    me.previewKeyword.update({text: 'text'});
                }
            });

            // TODO remove black
            //this.backgroundColor.menu.palette.colors[0] = 'FF0000';

            me.on({
                scope: me,
                // from CrudPlugin
                formchanged: function(){
                    var values = me.getNormalizedValues(),
                        preview = Bible.util.Format.keywordText(values.keywords.split(',')[0], values.style, values.cls);
                    me.previewKeyword.update({text: preview});
                }
            });
			
			// TODO test all cases for saveAndCloseButton
//			me.saveButton.on({
//				enable: function(){
//					me.saveAndCloseButton.enable();
//				},
//				disable: function(){
//					me.saveAndCloseButton.disable();
//				}
//			});
        },

        onSave: function(){
            //--console.debug('onSave');
            var me = this,
                values = me.getNormalizedValues(),
                record = me.grid.getSelectionModel().getSelected();
            me.grid.searchField.setValue('');
            if(record){
                //--console.debug('update', values);

                me.doRequest(values, function(response){
                    if(response.responseSuccess){
                        record.beginEdit();
                        record.set('style', values.style);
                        record.set('keywords', values.keywords);
                        record.set('cls', values.cls);
                        record.commit();
                        record.endEdit();
                    }
                });
            } else {
                //--console.debug('saveNew item');
                me.doRequest(values, function(response){
                    if(response.responseSuccess){
                        var index,
                            grid = this.grid,
                            store = grid.store;
                        values.id = response.responseJson.id;
						//--console.debug('created id', values.id);
                        record = new store.recordType(values, values.id);
                        store.add(record);
                        index = store.indexOf(record);
                        grid.getSelectionModel().selectRow(index);
                        (function(){
                            grid.view.focusRow(index);
                        }).defer(1);
                    }
                });
            }
        },

        doRequest: function(params, success){
            if(Bible.isLogged()){
                Ext.Ajax.request({
                    url: KEYWORDS_URL + '?action=save',
                    params: params,
                    scope: this,
                    success: success
                });
            } else {
                var response = {
                    responseSuccess: true,
                    responseJson: {
                        id: this.tmpSaveNumber++
                    }
                };
                // TODO saveNew item
                success.call(this, response);
                Bible.notifyNotLogged();
            }
        },

        /**
         * @return {Object} json {keywords: {String}, style: {String}}
         */
        getNormalizedValues: function(){
            var styles = this.form.getForm().getValues(),
                id = styles.id,
                keywords = Ext.util.Format.trim(styles.keywords),
                cls = styles.cls,
                enabled = 1, // TODO add in store
                style;
            delete styles.id;
            delete styles.keywords;
            delete styles.cls;
            delete styles.enabled;
            style = Bible.util.Format.getStyleAsString(styles, true);
            return {
                id: id,
                keywords: keywords,
                style: style,
                cls: cls,
                enabled: enabled
            };
        },

        onRowSelect: function(r){
            r = r || this.grid.getSelectionModel().getSelected();
            if(r){
                var values = {
                        id: r.get('id'),
                        keywords: r.get('keywords')
                    },
                    preview = Bible.util.Format.keywordText(r.get('keywords').split(',')[0], r.get('style'), r.get('cls')),
                    styles = Bible.util.Format.getStyleAsObject(r.get('style'));

                this.previewKeyword.update({text: preview});

                Ext.apply(values, styles);

                this.form.getForm().reset();
                //this.form.getForm().setValues(styles);
                this.form.setValues(values); // CrudMethod
            }
        },
		
		getBorderRadiusEditor: function(position){
			return {
				xtype: 'spinnerfield',
				name: 'border-' + position + '-radius',
				minValue: 0,
				maxValue: 50,
				width: 40,
				allowDecimals: false,
				value: 0,
				enableKeyEvents: true,
				setValue: function(v){
					if(typeof v == 'string'){
						v = v.replace('px', '');
					}
					Ext.form.SpinnerField.prototype.setValue.call(this, v);
				}
			};
		},

        getBorderItemsEditor: function(type){
            return [{
                xtype: 'spinnerfield',
                name: 'border-'+type+'-width',
                minValue: 0,
                maxValue: 4,
                width: 35,
                allowDecimals: false,
                value: 0,
                enableKeyEvents: true,
                setValue: function(v){
                    if(typeof v == 'string'){
                        v = v.replace('px', '');
                    }
                    Ext.form.SpinnerField.prototype.setValue.call(this, v);
                }
            },
            new Ext.form.ColorField({
                name: 'border-'+type+'-color',
                showHexValue: true,
                width: 75,
                value: 'FFFFFF',
                enableKeyEvents: true
            }),
            new Ext.form.ComboBox({
                hiddenName: 'border-'+type+'-style',
                mode: 'local',
                width: 75,
                typeAhead: true,
                forceSelection: true,
                triggerAction: 'all',
                displayField:'name',
                valueField: 'id',
                value: 'solid',
                enableKeyEvents: true,
                store: new Ext.data.ArrayStore({
                    fields: [{name: 'id'}, {name: 'name'}],
                    data: borderTypes
                }),
                listClass: 'x-combo-list-small',
                tpl: '<tpl for="."><div class="x-combo-list-item"><div style="border-'+type+'-style: {id};">&nbsp;{name}</div></div></tpl>'
            })];
        }
    });


})();


(function(){
    /**
	 * @class Bible.SearchGridPanel
	 * @extends Ext.grid.EditorGridPanel
	 */
	Bible.SearchGridPanel = Ext.extend(Ext.grid.GridPanel, {
        // while this is created for every BibleGrid can't be stateful
//        stateful: true,
//        stateID: 'Bible.SearchGridPanel',

        /**
         * @cfg {Bible.ReadContainer} activeReader
         */
        cls: 'bible-grid',
        //hideHeaders: true,
		stripeRows: true,
		//columnLines: true,
        autoExpandColumn: 'text',
		//loadMask: true,

		initComponent: function(){
            var me = this,
                colModel = new Ext.grid.ColumnModel({
                    columns: [
                        new Ext.grid.RowNumberer(),
                        {
                            id: 'text',
                            hideable: false,
                            menuDisabled: true,
                            header: 'Verset',
                            sortable: true,
                            dataIndex: 'text',
                            width: 200,
                            renderer: function(v, metaData, r, rowIndex, colIndex, store) {
                                v = Bible.rendererHighlight(v, metaData, r, rowIndex, colIndex, store);
                                return '<span class="verse-nr">(' + r.get('verse') + ')</span> ' + v;
                            }
                        }
                    ]
                });
            me.store = new Bible.data.BibleSearchStore();

            me.searchTypeStore = new Ext.data.ArrayStore({
                fields: ['id', 'name'],
                idIndex: 0,
                data : [
                    ['text', 'Text'],
                    ['any', 'ORICE cuvânt'],
                    ['all', 'TOATE cuvintele']
                ]
            });
            me.searchTypeCombo = new Ext.form.ComboBox({
                fieldLabel: i18n.searchType,
                anchor: '100%',
                //width: 200,
				displayField:'name',
                valueField: 'id',
                value: 'all',
                lastQuery: '',
                mode: 'local',
                selectOnFocus: true,
                forceSelection: true,
                triggerAction: 'all',
                editable: false,
                store: me.searchTypeStore,
                listeners: {
                    scope: me,
                    change: function(combo, newValue, oldValue){
                        //--console.debug('searchTypeCombo change', newValue, oldValue);
                        this.store.setBaseParam('type', newValue);
                    }
                }
            });

            me.searchIn = new Bible.form.ComboSearchFieldLocal({
                fieldLabel: i18n.searchIn,
				anchor: '100%',
                displayField:'name',
                valueField: 'id',
                lastQuery: '',
                mode: 'local',
                selectOnFocus: true,
                forceSelection: true,
                editable: true,
                typeAhead: true,
                allowBlank: true,
                triggerAction: 'all',
                emptyText: i18n.entireBible,
                listClass: 'x-combo-list-small x-combo-bible-books',
                //listWidth: 427,
				tpl: '<tpl for="."><div class="x-combo-list-item"><div>{id}</div>{name}</div></tpl>',
                store: new Bible.data.BibleBooksArrayStore(),
                listeners: {
                    scope: me,
                    clearfilter: function(){
                        //--console.debug('searchIn clearfilter');
                        this.store.setBaseParam('book', '');
                    },
                    change: function(combo, newValue, oldValue){
                        //--console.debug('searchIn change', newValue);
                        this.store.setBaseParam('book', newValue);
                    }
                }
            });

            me.searchField = new Ext.ux.form.SearchField({
                fieldLabel: i18n.search,
                store: this.store,
				anchor: '100%',
                filterType: true,
                onKeyup: true
            });
            me.store.searchField = me.searchField;

			Ext.apply(me, {
				hideMode: 'offsets',
				viewConfig: {
					autoFill: true,
					forceFit: true,
//					scrollOffset: 1,
                    templates: {
                        cell: new Ext.XTemplate(
                            '<td class="x-grid3-col x-grid3-cell x-grid3-td-{id} {css}" style="{style}" tabIndex="0" {cellAttr}>',
                                '<div class="x-grid3-cell-inner x-grid3-col-{id}" <tpl if="id != \'text\'">unselectable="on"</tpl> {attr}>{value}</div>',
                            '</td>'
                        )
                    }
				},
				sm: new Ext.grid.RowSelectionModel({
					singleSelect: true
				}),
				tbar: new Ext.Toolbar({
                    layout: 'fit',
                    style: {
                        padding: '5px 5px 2px 5px'
                    },
                    items: [{
                        xtype: 'container',
                        layout: 'form',
                        labelAlign: 'right',
                        hideMode: 'offsets',
                        items: [
                            me.searchTypeCombo,
                            me.searchIn,
                            me.searchField
                        ]
                    }]
                }),
                cm: colModel,
				bbar: new Ext.PagingToolbar({
                    buttonAlign: 'center',
                    pageSize: Bible.searchPageSize,
                    store: me.store
                })
			});

			Bible.SearchGridPanel.superclass.initComponent.call(me);
		},

		initEvents: function(){
            var me = this;
			Bible.SearchGridPanel.superclass.initEvents.apply(me, arguments);

            // TODO fix for chrome
//            if(Ext.isChrome){
//                //--console.warn('isChrome... fix combo width');
//                (function(){
//                    var c = this.getTopToolbar().get(0);
//                    c.setWidth(c.getWidth()-1);
//                    c.setWidth(c.getWidth()+1);
//                    //--console.warn('isChrome... tbar doLayout');
////                    c.doLayout(true);
//                }).defer(10, this);
//            }

            me.ctxMenu = new Ext.menu.Menu({
                items: [
//                    {
//                        text: i18n.copyText,
//                        icon: 'images/copy.png',
//                        scope: this,
//                        handler: function(){
//                            //--console.warn('TODO copyText');
//                        }
//                    },
//                    '-',
                    {
                        text: 'Deschide în coloana 1',
                        ref: 'openInFirst',
                        scope: me,
                        handler: me.openInFirstBibleGrid
                    },
                    {
                        text: 'Deschide în coloana 2',
                        ref: 'openInSecond',
                        scope: me,
                        handler: function(){
                            var bibleGrid = me.activeReader.secondGrid;
							me.activeReader.setBibleGridPage(me.selModel.getSelected(), me.searchField.getValue(), bibleGrid);
                        }
                    }
                ]
            });

            me.ctxMenu.on({
                scope: me,
                beforeshow: function(menu){
                    var actions = Bible.getActions(),
                        openInSecond = menu.openInSecond;
                    if(actions.l == 'hbox' || actions.l == 'vbox'){
                        openInSecond.show();
                    } else {
                        openInSecond.hide();
                    }
                }
            });

            me.on({
                scope: me,
                cellcontextmenu: function(thisGrid, rowIndex, cellIndex, e) {
                    e.stopEvent();
                    me.selModel.selectRow(rowIndex);
                    me.ctxMenu.showAt(e.getXY());
                },
                cellclick: function(grid, rowIndex, columIndex, e){
                    if(e.getTarget('.verse-nr')){
                        me.openInFirstBibleGrid();
                    }
                },
                celldblclick: function(grid, rowIndex, columnIndex, e){
                    //--console.debug('search grid celldblclick');
                    me.openInFirstBibleGrid();
                }
            });
		},

        openInFirstBibleGrid: function(){
            this.activeReader.setBibleGridPage(this.selModel.getSelected(), this.searchField.getValue());
        }
	});

    Ext.reg('searchgridpanel', Bible.SearchGridPanel);

})();
/**
 * @class Bible.grid.BookThemesGridPanel
 * @extends Ext.grid.EditorGridPanel
 */
(function(){
    var BookThemesGridPanel,
        BOOKS_URL = 'servlets/books.php';

    BookThemesGridPanel = Ext.extend(Ext.grid.EditorGridPanel, {
        cls: 'bible-themes-grid',
		stripeRows: true,
        columnLines: true,
        clicksToEdit: 1,

		initComponent: function(){
            var me = this;

            // TODO not on all browsers looks same
            me.textFieldEditor = new Ext.form.TextField({
                maxLength: 255,
//                style: 'padding: 2px 6px 3px 6px'
                style: 'padding: 3px 6px'
            });
            me.themeGridEditor = new Ext.grid.GridEditor(me.textFieldEditor, {
                offsets: [-2, -1]
            });

            me.store = new Ext.data.ArrayStore({
				//autoLoad: true,
                proxy: new Ext.data.HttpProxy(new Ext.data.Connection({
                    method: 'GET',
					url: BOOKS_URL,
					autoAbort: true
				})),
                baseParams: {
                    action: 'get_themes',
                    book: 1 // TODO temporary to load first book
                },
                root: 'data',
                idIndex: 0,
                fields: [
                    {name: 'cnumber', type: 'int'},
                    {name: 'theme', type: 'string'}
                ]
            });

            me.booksCombo = new Bible.form.BibleBooksComboBox({
//                value: me.defaultBook,
				infoTooltip: false,
                value: 1
            });

			Ext.apply(me, {
				viewConfig: {
					autoFill: true,
                    scrollOffset: 25,
					forceFit: true
				},
				sm: new Ext.grid.RowSelectionModel({
					singleSelect: true
				}),
				tbar: new Ext.Toolbar({
                    items: [
                        {
                            xtype: 'spacer',
                            cls: 'toolbar-icon'
                        },
                        me.booksCombo
                    ]
                }),
                cm: new Ext.grid.ColumnModel({
                    columns: [
                        new Ext.grid.RowNumberer({
                            dataIndex: 'cnumber',
                            width: 27
                        }),
                        {
                            id: 'book-themes',
                            hideable: false,
                            menuDisabled: true,
                            header: i18n.chapterTheme,
                            dataIndex: 'theme',
                            editor: me.themeGridEditor
                        },
                        {
                            id: 'book-action',
                            dataIndex: 'id',
                            width: 27,
                            fixed: true,
                            hideable: false,
                            menuDisabled: true,
                            renderer: function(v, metaData){
                                return '';
                            }
                        }
                    ]
                })
			});

			BookThemesGridPanel.superclass.initComponent.call(me);
		},

		initEvents: function(){
            var me = this,
                store = me.store;
			BookThemesGridPanel.superclass.initEvents.apply(me, arguments);

            me.booksComboChange(me.booksCombo.store.getAt(0));

            me.on({
                scope: me,
                afteredit: function(e){
                    var book = me.selectedBook;
                    Bible.updateDBObj('edit_list', e, BOOKS_URL + "?book=" + book, function(){
                        Bible.EventManager.fireEvent('themechange', me, book, e.record.id, e.value);
                    });
                }
            });

            me.mon(Bible.EventManager, {
                themechange: function(grid, book, chapter, newTheme){
                    //--console.info('themechange', book, chapter, newTheme);
                    if(me != grid && me.selectedBook == book){
                        // TODO temporary
                        me.store.reload();
                    }
                }
            });

            me.textFieldEditor.on('show', function() {
                var h = me.getView().getCell(store.indexOf(me.getSelectionModel().getSelected()), 2).clientHeight;
                this.setSize(this.getWidth() + 3, h);
            });

            me.booksCombo.on({
                select: function(combo, record, index){
                    me.booksComboChange(record);
                }
            });
		},

        booksComboChange: function(record){
            //--console.debug('booksComboChange', record.data);
            var book = record.get('id');
            this.selectedBook = book;
            this.store.load({
                params: {
                    book: book
                }
            });
        }
    });

    Bible.grid.BookThemesGridPanel = BookThemesGridPanel;

    Ext.reg('bookthemesgridpanel', BookThemesGridPanel);

})();
/**
 * @class Bible.ReadContainer
 * @extends Ext.Container
 */
Bible.ReadContainer = Ext.extend(Ext.Container, {
    layout: 'card',
    border: false,
    deferredRender: true,
    hideMode:'offsets',

    initComponent: function(){
        var me = this;
        me.firstGrid = new Bible.BibleGridPanel({
			id: 'base-grid',
            region: 'center',
            hashBook: 'b1'
        });
        me.secondGrid = new Bible.BibleGridPanel({
            hashBook: 'b2'
        });

        me.tabPanel = new Ext.TabPanel({
            hashBook: 'tabs',
            deferredRender: true,
            enableTabScroll:true,
            resizeTabs:true, // turn on tab resizing
            minTabWidth: 115,
            tabWidth:145,
            activeTab: Bible.defaults.layout == 'tabs' ? 0 : undefined,
            plugins: [
                new Ext.ux.TabCloseMenu(),
                new Bible.plugins.TabPanelAddButton({
                    maxLimit: 10,
                    addButton: new Ext.Button({
                        tooltip: 'Adaugă un Tab', // TODO i18n
                        iconCls: 'add-tab',
                        scope: me,
                        handler: function(){
                            //--console.debug('onBtnAddClick');
                            me.addBibleGridTab(true, true);
                        }
                    })
                })
            ],
            listeners: {
                tabchange: function(tabPanel, tab){
                    // fix bug when grid.bbar is not visible after tabchange
                    //tab.doLayout();
                    tab.getBottomToolbar().doLayout();
                }
            },
            items: [
                me.tab1 = new Bible.BibleGridPanel({
                    title: i18n.bible,
                    autoLoadChapter: Bible.defaults.layout != 'tabs',
                    //hashBook: 'b1',
                    border: false,
                    listeners: {
                        scope: me,
                        pagechange: me.tabPageChange
                    }
                })
            ]
        });

        var w = (Ext.getBody().getWidth()-10) / 2, // 5 from Search sidebar, 5 from splitter
            h = (Ext.getBody().getHeight()-48) / 2;  // 48 from tbar
        Ext.apply(me, {
            activeItem: Bible.defaults.layout != 'tabs' ? 0 : 1,
            items: [
                me.boxContainer = new Ext.Container({
                    hideMode:'offsets',
                    layout: 'border',
                    items: [
                        me.firstGrid,
                        me.bottomContainer = new Ext.Container({
                            id: 'bottom-preview',
                            layout:'fit',
                            region:'south',
                            height: h ? h : 250,
                            split: true,
                            border: true,
                            hidden: Bible.defaults.layout != 'vbox',
                            items: Bible.defaults.layout == 'vbox' ? me.secondGrid : []
                        }),
                        me.rightContainer = new Ext.Container({
                            id: 'right-preview',
                            layout:'fit',
                            region:'east',
                            width: w ? w : 500,
                            split: true,
                            border: true,
                            hidden: Bible.defaults.layout != 'hbox',
                            items: Bible.defaults.layout == 'hbox' ? me.secondGrid : []
                        })
                    ]
                }),
                me.tabPanel
            ]
        });

        /**
         * current view type
         * @type String
         * @property currentType
         */
        me.currentType = Bible.defaults.layout;

        Bible.ReadContainer.superclass.initComponent.call(me);

        me.readTabActions();
    },

    afterRender : function(){
        Bible.ReadContainer.superclass.afterRender.call(this);
        this.initEvents();
    },

    initEvents: function() {
        var me = this;

        me.tab1.on({
            scope: me,
            refclick: function(id, text){
                //--console.debug('refclick on tab1', id, text);
                var g = me.addBibleGridTab(false, false);
                if(g){
                    g.getVerseDetails(id, text);
                }
            }
        });

        me.firstGrid.on({
            scope: me,
            refclick: function(id, text){
                //--console.debug('refclick on firstGrid', id, text);
                //if(Bible.viewPort.panel.getTopToolbar().boxButton.pressed){
                if(me.currentType == 'box'){
                    Bible.viewPort.panel.getTopToolbar().hboxButton.toggle(true);
                }
                me.secondGrid.getVerseDetails(id, text);
            }
        });

        me.secondGrid.on({
            scope: me,
            refclick: function(id, text){
                //--console.debug('refclick on secondGrid', id, text);
                me.firstGrid.getVerseDetails(id, text);
            }
        });
    },

    addBibleGridTab: function(show, autoLoadChapter){
        var me = this;
        if(me.tabPanel.items.getCount() < 10){ //maxLimit
            var grid = new Bible.BibleGridPanel({
                //xtype: 'biblegridpanel',
                title: i18n.bible,
                closable:true,
                autoLoadChapter: autoLoadChapter,
                listeners: {
                    scope: me,
                    pagechange: me.tabPageChange
                }
            });
            //this.tabPanel.add(grid).show();
            me.tabPanel.add(grid);
            if(show){
                grid.show();
            }
            grid.on({
                scope: me,
				destroy: function(){
					me.setTabActions();
				},
                refclick: function(id, text){
                    //--console.debug('refclick on tab', id, text);
                    var g = this.addBibleGridTab(false, false);
                    if(g){
                        g.getVerseDetails(id, text);
                    }
                }
            });
            return grid;
        } else {
            //--console.warn('can not add more that 10 tabs');
            return false;
        }

    },

    // private
    tabPageChange: function(grid, params){
        var title = grid.booksStore.getById(params.book).get('name') + ' ' + params.chapter;
        if(title.length > 15){
            title = '<span qtip="'+title+'">'+title+'</span>';
        }
        grid.setTitle(title);
        this.setTabActions();
    },

    /**
     *
     */
    setTabActions: function(){
        var me = this,
            tabPanel = me.tabPanel,
            action = [],
            separator = '.';
        if(!me.pauseChangeUrl){
            tabPanel.items.each(function(g){
                action.push(g.booksCombo.getValue() + separator + g.chaptersCombo.getValue());
            });
            Bible.setActions(tabPanel.hashBook, action.join('-'));
        }
    },

    /**
     *
     */
    readTabActions: function(){
        var me = this,
            grid,
            chapter,
            action = Bible.getAction(me.tabPanel.hashBook);
        //--console.debug('readTabActions: ', action);
        if(action){
            action = action.split('-');
            me.pauseChangeUrl = true;
            Ext.each(action, function(params, index){
                chapter = params.split('.');
                //--console.debug('params, chapter, index: ', params, chapter, index);
                if(index){
                    grid = me.addBibleGridTab(false, false);
                    if(grid){
                        grid.setPage({
                            book: chapter[0],
                            chapter: chapter[1]
                        });
                    }
                } else {
                    //--console.warn('set first grid values (title and store is not changed)');
                    grid = me.tab1;
                    grid.setPage({
                        book: chapter[0],
                        chapter: chapter[1]
                    });
                }
            });
            me.pauseChangeUrl = false;
        }
    },

    /**
     * @param {Ext.Button} button
     */
    moveSecondView : function(button, pressed){
        var me = this,
            bottom = me.bottomContainer,
            right = me.rightContainer,
            second = me.secondGrid,
            tabPanel = me.tabPanel,
            layout = this.getLayout(),
            action,
            separator = '.';
        if(pressed){
            me.currentType = button.type;
            switch(button.type){
                case 'vbox':
                    layout.setActiveItem(0);
                    right.hide();
                    bottom.add(me.secondGrid);
                    bottom.show();
                    bottom.ownerCt.doLayout();
                    action = second.booksCombo.getValue() + separator + second.chaptersCombo.getValue();
                    Bible.setActions(second.hashBook, action);
                    Bible.removeAction(tabPanel.hashBook);
                    break;
                case 'hbox':
                    layout.setActiveItem(0);
                    bottom.hide();
                    right.add(me.secondGrid);
                    right.show();
                    right.ownerCt.doLayout();
                    action = second.booksCombo.getValue() + separator + second.chaptersCombo.getValue();
                    Bible.setActions(second.hashBook, action);
                    Bible.removeAction(tabPanel.hashBook);
                    break;
                case 'box':
                    layout.setActiveItem(0);
                    if(second.ownerCt){
                        second.ownerCt.hide();
                        second.ownerCt.ownerCt.doLayout();
                    }
                    Bible.removeAction(second.hashBook);
                    Bible.removeAction(tabPanel.hashBook);
                    break;
                case 'tabs':
                    me.getLayout().setActiveItem(1);
                    if(!tabPanel.getActiveTab()){
                        tabPanel.setActiveTab(0);
                    }
                    me.setTabActions();
                    Bible.removeAction(me.firstGrid.hashBook);
                    Bible.removeAction(second.hashBook);
                    break;
            }
//            Bible.setActions('layout', button.type);
            Bible.setActions('l', button.type);
        }
    },
	
	setBibleGridPage: function(record, searchValue, bibleGrid){
		//--console.debug('setBibleGridPage', record, searchValue);
		bibleGrid = bibleGrid || this.firstGrid;
		if(this.currentType == 'tabs'){
			//--console.debug('activeReader');
			bibleGrid = this.tabPanel.getActiveTab();
		}
		if(searchValue){
			bibleGrid.searchField.setValue(searchValue);
		}
		var params = {
			book: record.get('bnumber'),
			chapter: record.get('cnumber')
		};
		if(!bibleGrid.isEqual(params)){
			bibleGrid.setPage(params, record.get('vnumber'));
		} else {
			//--console.debug('store unchanged: selectRow & focusRow');
			bibleGrid.selectVerse(record.get('vnumber'));
		}
	}
});

Ext.reg('readcontainer', Bible.ReadContainer);
Ext.BLANK_IMAGE_URL = 'js/ext-3.4.1/resources/images/default/s.gif';

Ext.onReady(function() {

    var loggedUser = Bible.loggedUser;

    /**
     * functioneaza in felul urmator:
     * daca detecteaza ca browserul are suport pt local storage, isi tine state-ul in local storage,
     * iar daca nu are local storage, nu foloseste cookie-uri, ci foloseste un hidden form
     *
     * Daca userul e logat, atunci ii dam ca parametru si un user id
     */
    Ext.state.Manager.setProvider(new Ext.ux.state.LocalProvider({
        userid: loggedUser ? loggedUser.email: 'app.bibliaonline.ro'
    }));

    Ext.QuickTips.init();

    Ext.apply(Ext.QuickTips.getQuickTip(), {
        dismissDelay: false,
        showDelay : 700
    });

    var //cookie = readCookie("style"),
//        selectedStyle = cookie ? cookie : getPreferredStyleSheet(),
        actions = Bible.getActions();

    //defaults = Ext.copyTo({}, actions, 'layout');
    //Ext.apply(Bible.defaults, defaults);
    if(actions.l){
        Bible.defaults.layout = actions.l;
    }
    if(actions.z){
        Bible.defaults.fontSize = actions.z;
    }

    //--console.debug('actions:', actions);

    // TODO chrome test combo width
//    new Bible.SearchGridPanel({
//        height: 500,
//        width: 600,
//        renderTo: Ext.getBody()
//    });
//    return;

    var desktop = new Bible.ReadContainer({
        id: 'desktop'
    });

    desktop.firstGrid.selectVerseAfterLoad(1); // TODO get from link
	
	var searchStore = new Bible.data.BibleSearchStore();	
    var resultTpl = new Ext.XTemplate(
		'<tpl for=".">',
			'<div class="x-combo-list-item" style="white-space: normal;">',
				'<span class="verse-nr">({verse})</span> {[this.rendererHighlight(values.text)]}',
			'</div>',
		'</tpl>',
		{
			rendererHighlight: function(text){
				return Bible.highlightTerms(text, searchStore).text;
			}
		}
	);
    var searchField = new Ext.form.ComboBox({
        store: searchStore,
        displayField:'text',
        typeAhead: false,
		emptyText: 'Caută în Biblie...',
        loadingText: 'Căutare...',
		queryDelay: 300,
        width: 170,
		listWidth: 400,
        pageSize: 10,
		minChars: 3,
		selectOnFocus: true,
		triggerClass:'x-form-search-trigger',
        tpl: resultTpl,
		initQuery : function(){
			//var split = searchField ? (searchField.split || (searchField.filterType && searchField.store.baseParams.type != 'text')) : false;
			var highlights = Ext.util.Terminology.createHighlightsTerms(this.getRawValue(), 2, true);
			this.store.searchField = {
				highlightsTerms: highlights.terms
			}
			Ext.form.ComboBox.prototype.initQuery.call(this);
		},
        onSelect: function(record){
			//--console.info('selected', record);
			desktop.setBibleGridPage(record, this.getRawValue());
			this.collapse();
        }/*,
		listeners: {
			select: function(combo, record, index){
				desktop.setBibleGridPage(record, this.getRawValue());
			}
		}*/
    });

	var viewPort = new Ext.Viewport({
        layout: 'fit',
        cls: 'font-size-' + Bible.defaults.fontSize,
		currentFontSize: 'font-size-' + Bible.defaults.fontSize,
        fontSizes: [11, 12, 14, 16, 18, 20, 22, 24, 28],
        items: new Ext.Panel({
            ref: 'panel',
            layout: 'border',
            border: false,
            tbar: new Ext.Toolbar({
                style: 'borderBottom: 0; borderLeft: 1px solid #99BBE8;',
                items: [
                    ' ',
                    {
                        ref: 'boxButton',
                        tooltip: 'O Coloană',
                        type: 'box',
                        iconCls: 'x-cols-single-icon',
                        pressed: Bible.defaults.layout == 'box',
                        enableToggle: true,
                        allowDepress: false,
                        toggleGroup:'cols-group',
                        scope: desktop,
                        toggleHandler: desktop.moveSecondView
                    },
                    {
                        ref: 'vboxButton',
                        tooltip: '2 Coloane (Vertical)',
                        type: 'vbox',
                        iconCls: 'x-cols-vbox-icon',
                        pressed: Bible.defaults.layout == 'vbox',
                        enableToggle: true,
                        allowDepress: false,
                        toggleGroup:'cols-group',
                        scope: desktop,
                        toggleHandler: desktop.moveSecondView
                    },
                    {
                        ref: 'hboxButton',
                        tooltip: '2 Coloane (Orizontal)',
                        type: 'hbox',
                        iconCls: 'x-cols-hbox-icon',
                        pressed: Bible.defaults.layout == 'hbox',
                        enableToggle: true,
                        allowDepress: false,
                        toggleGroup:'cols-group',
                        scope: desktop,
                        toggleHandler: desktop.moveSecondView
                    },
                    {
                        ref: 'tabsButton',
                        tooltip: 'Multiple File',
                        type: 'tabs',
                        pressed: Bible.defaults.layout == 'tabs',
                        enableToggle: true,
                        allowDepress: false,
                        toggleGroup:'cols-group',
                        iconCls: 'tabs',
                        scope: desktop,
                        toggleHandler: desktop.moveSecondView
                    },
                    '-',
                    {
                        tooltip: i18n.zoomOut,
                        iconCls: 'font-zoom-out-icon',
                        handler: function(){
                            viewPort.removeClass(viewPort.currentFontSize);
                            var i = viewPort.fontSizes.indexOf(parseInt(viewPort.currentFontSize.replace('font-size-', '')));
                            i = i > 0 ? i-1 : i;
                            viewPort.currentFontSize = 'font-size-' + viewPort.fontSizes[i];
                            viewPort.addClass(viewPort.currentFontSize);
                            Bible.setActions('z', viewPort.fontSizes[i]);
                        }
                    },
                    {
                        tooltip: i18n.zoomIn,
                        iconCls: 'font-zoom-in-icon',
                        handler: function(){
                            viewPort.removeClass(viewPort.currentFontSize);
                            var i = viewPort.fontSizes.indexOf(parseInt(viewPort.currentFontSize.replace('font-size-', '')));
                            i = i+1 < viewPort.fontSizes.length ? i+1 : i;
                            viewPort.currentFontSize = 'font-size-' + viewPort.fontSizes[i];
                            viewPort.addClass(viewPort.currentFontSize);
                            Bible.setActions('z', viewPort.fontSizes[i]);
                        }
                    },
					'-',
					searchField,
					{
						tooltip: i18n.advancedSearch,
                        iconCls: 'icon-find',
						handler: function(){
							viewPort.search.toggleCollapse(true);
						}
					},
                    '-',
                    {
                        tooltip: i18n.bookOverview,
                        //text: i18n.bookOverview,
						iconCls: 'icon-overview',
                        handler: function(){
                            if(!this.bookOverviewWin){
                                this.bookOverviewWin = new Ext.Window({
                                    title: i18n.bookOverview,
									iconCls: 'icon-overview',
//                                modal: true,
                                    maximizable: true,
                                    width: 700,
                                    height: 400,
                                    layout: 'fit',
                                    border: false,
                                    closeAction: 'hide',
                                    items: new Bible.grid.BookThemesGridPanel()
                                });
                            }

                            this.bookOverviewWin.show();
                        }
                    },
                    '->',
//                    {
//                        xtype: 'combo',
//                        width: 100,
//                        mode: 'local',
//                        value: selectedStyle ? selectedStyle : 'blue',
//                        editable: false,
//                        allowBlank: false,
//                        selectOnFocus: true,
//                        lastQuery: '',
//                        lazyInit: false,
//                        //lazyRender: false,
//                        forceSelection: true,
//                        typeAhead: true,
//                        triggerAction: 'all',
//                        displayField:'name',
//                        valueField: 'id',
//                        store: new Ext.data.ArrayStore({
//                            fields: ['id', 'name'],
//                            idIndex: 0,
//                            data : [['blue', 'Blue Theme'],['gray', 'Gray Theme']]
//                        }),
//                        listeners: {
//                            select: function(combo, record, index){
//                                var name = record.get('id');
//                                //--console.debug('change theme to: ', name);
//                                setActiveStyleSheet(name);
//                            }
//                        }
//                    },
                    {
                        text: i18n.preferences,
                        iconCls: 'preferences',
//                        hidden: !Bible.loggedUser,
                        handler: function(){
                            Bible.showPreferencesWin();
                        }
                    },
                    {
                        xtype: 'tbseparator'
//                        hidden: !Bible.loggedUser
                    },
                    {
                        tooltip: i18n.info,
                        iconCls: 'icon-docs',
                        handler: function(){
                            Bible.showDocs();
                        }
                    },
                    '-',
                    {
                        text: !loggedUser ? i18n.login : i18n.logout,
						iconCls: 'login',
                        handler: function(){
                            if(!Bible.loggedUser){
                                Bible.doLogin();
                            } else {
                                Bible.doLogout();
                            }
                        }
                    },
                    {
                        xtype: 'tbseparator',
                        hidden: !!loggedUser
                    },
                    {
                        text: i18n.register,
                        hidden: !!loggedUser,
						iconCls: 'user_add',
                        handler: function(){
                            Bible.showRegisterForm();
                        }
                    }
                ]
            }),

            items:[{
                ref: '../search',
                region: 'west',
                title: i18n.search,
                xtype: 'searchgridpanel',
                activeReader: desktop,
                split: true,
                width: 325,
                minSize: 200,
                maxSize: 400,
                collapsed: true,
                collapseMode:'mini',
                collapsible: true
            },
            {
                region: 'center',
                xtype: 'container',
                layout: 'fit',
                border: false,
                items: desktop
            }],

             bbar: new Ext.Toolbar({
                style: 'borderTop: 0; borderLeft: 1px solid #99BBE8;',
                items: [
                    {
                        xtype: 'tbtext',
                        text: loggedUser ? loggedUser.email : ''
                    },
                    '->',
                    {
                        id: 'app-name-version',
                        xtype: 'tbtext',
                        text: '&copy; Biblia pentru Studiu '+ Bible.version + ' <span class="author">(autor Matei Nicolae)</span>'
                    }
                ]
            })
        })
    });

    Bible.viewPort = viewPort;

    if(actions.action == 'resetpass'){
        Bible.showResetPassWin(true);
        Bible.removeAction('action');
    }
});
